码迷,mamicode.com
首页 > 其他好文 > 详细

状压dp入门第一题 poj3254

时间:2017-09-05 23:11:37      阅读:179      评论:0      收藏:0      [点我收藏+]

标签: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 }

 

状压dp入门第一题 poj3254

标签:long   int   ios   mem   scan   状压dp   lan   log   ini   

原文地址:http://www.cnblogs.com/stranger-/p/7482161.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!