标签:long int ios mem scan 状压dp lan log ini
题目链接 http://poj.org/problem?id=3254
转自http://blog.csdn.net/harrypoirot/article/details/23163485
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <iostream> 6 #include <sstream> 7 #include <algorithm> 8 #include <string> 9 #include <queue> 10 #include <vector> 11 using namespace std; 12 const int maxn= 1e5 + 10; 13 const int inf = 0x3f3f3f3f; 14 typedef long long ll; 15 #define mod 100000000 16 int M,N,top = 0; 17 //top表示每行最多的状态数 18 19 int state[600],num[110]; 20 //state存放每行所有的可行状态(即没有相邻的状态 21 // 22 23 int dp[20][600]; 24 //dp[i][j]:对于前i行数据,每行有前j种可能状态时的解 25 int cur[20]; 26 //cur[i]表示的是第i行整行的情况 27 28 inline bool ok(int x){ //判断状态x是否可行 29 if(x&x<<1) return false;//若存在相邻两个格子都为1,则该状态不可行 30 return true; 31 } 32 void init(){ //遍历所有可能的状态 33 top = 0; 34 int total = 1 << N; //遍历状态的上界 35 for(int i = 0; i < total; ++i){ 36 if(ok(i))state[++top] = i; 37 } 38 } 39 inline bool fit(int x,int k){ //判断状态x 与第k行的实际状态的逆是否有‘重合’ 40 if(x&cur[k])return false; //若有重合,(即x不符合要求) 41 return true; //若没有,则可行 42 } 43 44 int main(){ 45 while(scanf("%d%d",&M,&N)!= EOF){ 46 init(); 47 memset(dp,0,sizeof(dp)); 48 for(int i = 1; i <= M; ++i){ 49 cur[i] = 0; 50 int num; 51 for(int j = 1; j <= N; ++j){ //输入时就要按位来存储,cur[i]表示的是第i行整行的情况,每次改变该数字的二进制表示的一位 52 scanf("%d",&num); //表示第i行第j列的情况(0或1) 53 if(num == 0) //若该格为0 54 cur[i] +=(1<<(N-j)); //则将该位置为1(注意要以相反方式存储,即1表示不可放牧 55 } 56 } 57 for(int i = 1;i <= top;i++){ 58 if(fit(state[i],1)){ //判断所有可能状态与第一行的实际状态的逆是否有重合 59 dp[1][i] = 1; //若第1行的状态与第i种可行状态吻合,则dp[1][i]记为1 60 } 61 62 } 63 64 /* 65 状态转移过程中,dp[i][k] =Sigma dp[i-1][j] (j为符合条件的所有状态) 66 */ 67 for(int i = 2; i <= M; ++i){ //i索引第2行到第M行 68 for(int k = 1; k <= top; ++k){ //该循环针对所有可能的状态,找出一组与第i行相符的state[k] 69 if(!fit(state[k],i))continue; //判断是否符合第i行实际情况 70 for(int j = 1; j <= top ;++j){ //找到state[k]后,再找一组与第i-1行符合,且与第i行(state[])不冲突的状态state[j] 71 if(!fit(state[j],i-1))continue; //判断是否符合第i-1行实际情况 72 if(state[k]&state[j])continue; //判断是否与第i行冲突 73 dp[i][k] = (dp[i][k] +dp[i-1][j])%mod; //若以上皆可通过,则将‘j‘累加到‘k‘上 74 } 75 } 76 } 77 int ans = 0; 78 for(int i = 1; i <= top; ++i){ //累加最后一行所有可能状态的值,即得最终结果!!!泥马写注释累死我了终于写完了! 79 ans = (ans + dp[M][i])%mod; 80 } 81 printf("%d\n",ans); 82 } 83 }
标签:long int ios mem scan 状压dp lan log ini
原文地址:http://www.cnblogs.com/stranger-/p/7482161.html