状压DP学习
1. POJ3254 Corn Fields
设dp[i][j] 表示第i行状态为j的合法方案的个数
dp[i][j] = dp[i][j] + dp[i-1][k] 当然状态方程很好写,重点在与怎么判断是否是合法的方案,鉴于这题比较简单就不细说
(1)当前行内,不能有相邻的两个1
(2)当前行与上一行是否冲突
(3)当前状态是否满足题目给出的图
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <string> 5 #include <iostream> 6 #include <algorithm> 7 #include <cmath> 8 #include <vector> 9 #include <map> 10 using namespace std; 11 const int maxn = 13; 12 const int maxv = 50005; 13 const int INF = 0x3f3f3f3f; 14 const int mod = 1e8; 15 typedef __int64 LL; 16 int dp[maxn][1<<maxn]; 17 int a[maxn]; 18 bool isok(int j) 19 { 20 return !(j & (j<<1)); 21 } 22 int main() 23 { 24 // freopen("in.txt","r",stdin); 25 // freopen("out.txt","w",stdout); 26 int n,m; 27 while(cin>>n>>m) 28 { 29 memset(dp,0,sizeof(dp)); 30 memset(a,0,sizeof(a)); 31 for(int i = 1;i<=n;++i) 32 for(int j = 0;j<m;++j) 33 { 34 int t; 35 scanf("%d",&t); 36 if(t)a[i] = a[i]|(1<<j); 37 } 38 dp[0][0] = 1; 39 m = 1<<m; 40 for(int i = 1;i<=n;++i) 41 for(int j = 0;j<m;++j)if((a[i]|j)==a[i] && isok(j)) 42 for(int k = 0;k<m;++k)if(!(j & k)) 43 dp[i][j] = (dp[i][j]+dp[i-1][k])%mod; 44 int ans = 0; 45 for(int i = 0;i<m;++i) 46 ans = (ans+dp[n][i])%mod; 47 cout<<ans<<endl; 48 } 49 50 return 0; 51 }
弱者究竟为何而战?!