首页 > 代码库 > POJ 3254 Corn Fields (状压DP+滚动数组)
POJ 3254 Corn Fields (状压DP+滚动数组)
题目地址:POJ 3254
状压水题。
先预处理出每行所有可能出现的情况。然后可以用vector存起来。
然后先处理出第一行所有的情况。然后再从第二行开始不断与上一行进行状态转移,状态转移很简单就不说了。
最后统计出最后一行的个数和就可以了。
代码如下;
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> using namespace std; #define LL __int64 const int mod=100000000; const int INF=0x3f3f3f3f; int a[20][20]; int dp[3][1<<13]; vector<int>vec[13]; bool Judge(int x, int y, int m) { int i; for(i=0; i<m; i++) { if((x&(1<<i))&&(y&(1<<i))) return 0; } return 1; } int main() { int n, m, i, j, tot, k, h, flag, ans, tmp; scanf("%d%d",&n,&m); for(i=0; i<n; i++) { for(j=0; j<m; j++) { scanf("%d",&a[i][j]); } } tot=1<<m; for(i=0; i<n; i++) { for(j=0; j<tot; j++) { flag=0; for(k=0; k<m; k++) { if(j&(1<<k)) { if(!a[i][k]) { flag=1; break; } if(k>0&&(j&(1<<k-1))) { flag=1; break; } } } if(!flag) vec[i].push_back(j); } } for(i=0; i<vec[0].size(); i++) { dp[0&1][vec[0][i]]=1; } //printf("%d\n",vec[0].size()); ans=0; for(i=1; i<n; i++) { memset(dp[i&1],0,sizeof(dp[i&1])); for(j=0; j<vec[i].size(); j++) { tmp=vec[i][j]; for(k=0; k<vec[i-1].size(); k++) { if(Judge(tmp,vec[i-1][k], m)) { dp[i&1][tmp]+=dp[i-1&1][vec[i-1][k]]; if(dp[i&1][tmp]>=mod) dp[i&1][tmp]%=mod; } } if(i==n-1) { ans+=dp[i&1][tmp]; if(ans>=mod) ans%=mod; //printf("%d\n",ans); } } } if(n==1) { ans=vec[0].size(); } printf("%d\n",ans); return 0; }
POJ 3254 Corn Fields (状压DP+滚动数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。