【状态压缩DP】【POJ3254】【POJ1185】 入门题
2013-08-11 19:46
435 查看
【POJ3254】题目直达车: POJ 3254 Corn Fields
题意:有一个m*n(n、m<=12)的网格,每个方格只能是0、1,从网格中选一部分
(可为0)方格(只能选1的方格),不能取相邻(包括四个方向)的两个,
问有多少种选法。
分析:因为n、m的数据比较小,所以可用状态DP,即:用一个整数p表示一行选方格
的情况,p的二进制为1时说明这位置的方格被选,反之不选。用时,将每一行
的方格也当成二进制化为一个整数q,但为了更好地判断状态p的可行性,可以将
网格中的0、1互换,如:0 1 0 => 1 0 1, 则q=5。那么只考虑这一行时,判断
p的可行性的方法是:当(p&q)=0时表示可以这么选(即p状态),反之不能。
那么,判断相邻两行的状态可行性的方法如下:
设第i-1行状态为pi-1,第i行状态为pi,则:当(pi-1&pi)=0时为可行,反之则不行。
转移方程:
代码:
【POJ1185】题目直达车:
POJ 1185 炮兵阵地
分析:
列( <=10 )的数据比较小, 一般会想到状压DP.
Ⅰ、如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举)。
Ⅱ、用DFS搜出所有可能表示状态的整数(二进制1表示可以放,0则不能)。
Ⅲ、对每一行的地行进行状态处理(p[i]表示第i行地形的状态),二进制‘H’转1,‘P’转0;
Ⅳ、用dp[i][j][k]表示第i行,且i行状态为j,i-1行状态为k时,最多能放置的量。
Ⅴ、对于第i行的可行状态必须满足:
⒈ j & k =0 且 j & t =0 (t为第i-2行放置状态)与前两行匹配,即不互相攻击。
⒉ j & p[i] = 0 与地形匹配,即只放平原地带。
Ⅵ、转移方程:dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j])
(num[j]为第j种状态中放置炮兵的数量)
第一次做状态DP, 参考(题解报告)的思路才敲出来
代码:
题意:有一个m*n(n、m<=12)的网格,每个方格只能是0、1,从网格中选一部分
(可为0)方格(只能选1的方格),不能取相邻(包括四个方向)的两个,
问有多少种选法。
分析:因为n、m的数据比较小,所以可用状态DP,即:用一个整数p表示一行选方格
的情况,p的二进制为1时说明这位置的方格被选,反之不选。用时,将每一行
的方格也当成二进制化为一个整数q,但为了更好地判断状态p的可行性,可以将
网格中的0、1互换,如:0 1 0 => 1 0 1, 则q=5。那么只考虑这一行时,判断
p的可行性的方法是:当(p&q)=0时表示可以这么选(即p状态),反之不能。
那么,判断相邻两行的状态可行性的方法如下:
设第i-1行状态为pi-1,第i行状态为pi,则:当(pi-1&pi)=0时为可行,反之则不行。
转移方程:
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int mod=1000000000; int n,m; vector<int>M; // 状态 int a[15], p[15]={0}; long long dp[13][4500]; void dfs(int x) { // 找出长度为n的所有状态 if(x==-1) { int u=0; for(int i=0; i<n; ++i) if(a[i]) u|=(1<<i); M.push_back(u); return; } for(int i=0; i<=1; ++i){ if(i&&a[x+1]) break; a[x]=i; dfs(x-1); } } int main() { while(~scanf("%d%d",&m,&n)) { memset(a,0,sizeof(a)); memset(dp,0,sizeof(dp)); M.clear(); dfs(n-1); dp[0][0]=1LL; int len=M.size(); for(int i=1; i<=m; ++i) { p[i]=0; for(int j=0; j<n; ++j){ int x; scanf("%d",&x); p[i]|=(1-x)<<j; } for(int j=0; j<len; ++j) if((M[j]&p[i])==0) for(int k=0; k<len; ++k) if((M[k]&p[i-1])==0&&(M[j]&M[k])==0) dp[i][j]=(dp[i][j]+dp[i-1][k])%mod; } long long ans=0; for(int j=0; j<len; ++j) ans=(ans+dp[m][j])%mod; printf("%lld\n", ans); } return 0; }
【POJ1185】题目直达车:
POJ 1185 炮兵阵地
分析:
列( <=10 )的数据比较小, 一般会想到状压DP.
Ⅰ、如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举)。
Ⅱ、用DFS搜出所有可能表示状态的整数(二进制1表示可以放,0则不能)。
Ⅲ、对每一行的地行进行状态处理(p[i]表示第i行地形的状态),二进制‘H’转1,‘P’转0;
Ⅳ、用dp[i][j][k]表示第i行,且i行状态为j,i-1行状态为k时,最多能放置的量。
Ⅴ、对于第i行的可行状态必须满足:
⒈ j & k =0 且 j & t =0 (t为第i-2行放置状态)与前两行匹配,即不互相攻击。
⒉ j & p[i] = 0 与地形匹配,即只放平原地带。
Ⅵ、转移方程:dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j])
(num[j]为第j种状态中放置炮兵的数量)
第一次做状态DP, 参考(题解报告)的思路才敲出来
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<vector> using namespace std; int p[105],dp[105][65][65]; vector<int>M[11]; int a[11],n,m; void DFS(int k,int t){ ///搜索m=t时如果全为'P'可以表示状态的整数 if(k==t){ int p=0; for(int i=0;i<t;++i) if(a[i]) p=p|(1<<i); M[t].push_back(p); /// 记下能表示状态的整数 return; } for(int i=0;i<=1;++i){ if(i&&((k&&a[k-1])||(k>1&&(a[k-1]||a[k-2])))) continue; a[k]=i; DFS(k+1,t); } } int main(){ for(int i=1;i<=10;++i) DFS(0,i); while(~scanf("%d%d",&n,&m)&&n+m){ p[0]=0; ///num[i]记下用第i种状态(整数M[m][i]表示) 中设了多少炮兵部队 int num[65], len=M[m].size(); for(int i=0;i<len;++i) num[i]=__builtin_popcount( M[m][i] ); ///计算M[m][i]中二进制中1的个数 memset(dp,0,sizeof(dp)); int Max=0; for(int i=1;i<=n;++i){ char ch[105]; scanf("%s",ch); p[i]=0; //预处理地形(1代表'H',0代表'P') for(int j=0;j<m;++j) if(ch[j]=='H') p[i]|=(1<<j); if(i==1){ //初始化第一行所有布置情况 for(int k=0; k<len; ++k) for(int j=0; j<len; ++j){ if(!(M[m][k]&p[1])) dp[1][k][j]=num[k]; else dp[1][k][j]=0; Max=max(Max,dp[1][k][j]); } continue; } for(int j=0; j<len; ++j)//当前行 if(!(M[m][j]&p[i])) //与 地形匹配 for(int k=0; k<len; ++k)//i-1 if(!(M[m][k]&p[i-1])&&!(M[m][k]&M[m][j]))//与 地形、i-1行匹配 for(int t=0; t<len; ++t)//i-2 //与 地形、i-1行、i-2行匹配 if(!(M[m][t]&p[i-2])&&!(M[m][t]&M[m][k])&&!(M[m][t]&M[m][j])){ dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j]); if(i==n)Max=max(dp[i][j][k],Max); } } printf("%d\n",Max); } return 0; }
相关文章推荐
- 状态压缩dp入门[HDU1074][HDU1065][POJ3254][POJ1185][HDU4359][POJ3311][POJ2411]
- 状态压缩dp入门题 POJ 1185 炮兵阵地
- Poj 1185 炮兵阵地(状态压缩dp 入门题)
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- poj3254 poj1185 状态压缩DP
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- poj 1185 炮兵阵地(状态压缩DP)
- poj 3250 状态压缩dp入门
- poj 1185(状态压缩dp)
- POJ 1185 状态压缩DP
- poj 1185 状态压缩DP
- POJ 1185 状态压缩DP
- Poj - 3254 Corn Fields (状态压缩dp入门第一题(详解
- POJ1185炮兵阵地(DP状态压缩)
- poj1185 状态压缩Dp
- poj1185炮兵阵地(状态压缩DP)