2017.7.26 奇怪的道路 失败总结

来源:互联网 发布:mac 地址 修改 安卓 编辑:程序博客网 时间:2024/06/05 09:59

做不出来主要是老想着用2^30存每个点的状态,用0 1表示连边奇偶,,就被限制住了

实际上我们应该注意到k=8,这样我们就只用记录前k个、、

其实就是递推的思路,每次加入一个新点,枚举这个点与前K个点各种情况的连边,再考虑连与不连有什么影响

再就是不同点的转移要注意保持合法性

注意状态记录从右往左,这是因为>>正好可以削掉一个边界


只要能把所有情况都考虑进来,完成每一个点加入前所有其他点的状态的完整, 就是成功的dp


码:

#include<iostream>#include<cstdio>using namespace std;#define p 1000000007int n,m,K,k,f[35][35][(1<<9)][10];int main(){scanf("%d%d%d",&n,&m,&K);f[2][0][0][0]=1;for(int i=2;i<=n;i++)for(int j=0;j<=m;j++)for(int k=0;k<(1<<(K+1));k++){for(int l=0;l<K;l++){if(f[i][j][k][l]){f[i][j][k][l+1]+=f[i][j][k][l];                  f[i][j][k][l+1]%=p;              //放过这次连边机会,给下一个连边 if(j<m&&i-K+l>0){f[i][j+1][k^(1<<K)^(1<<l)][l]+=f[i][j][k][l];f[i][j+1][k^(1<<K)^(1<<l)][l]%=p;     //连边之后的影响     }   }}if((k&1)==0&&f[i][j][k][K])f[i+1][j][k>>1][0]=f[i][j][k][K];//因为K个以前的再也没有机会合法,所以必须K个前满足才能转给下一个 }printf("%d",f[n+1][m][0][0]);}

做题一定不要钻一个几乎不可能的点,要考虑从其他角度切入(尤其是dp的状态设计)

还有就是不要看到题目奇怪就觉得不会了,这时应该尽量把题目压缩,然后针对题目奇怪的地方找角度切入(如对8用状压、)


原创粉丝点击