poj1185炮兵阵地
2016-05-09 16:47
295 查看
题目链接:传送门
题目思路:状态压缩DP(详见注释)
题目思路:状态压缩DP(详见注释)
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson root<<1,l,mid #define rson root<<1|1,mid+1,r #define fi first #define se second #define seg int root,int l,int r #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) #define Min(x,y) (x<y?x:y) #define Max(x,y) (x>y?x:y) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 100000007 #define inf 0x3f3f3f3f #define N 10005 #define maxn 1000050 typedef long long LL; typedef pair<int,int> PII; char str[105]; int pic[105],n,m,ans,all; int state[1005],num[1005],cnt;///state里面保存的是可以放炮台的情况 int dp[105][105][105]; ///二进制位为1表示放炮台,和pic中的不一样 int judge(int x){ ///判断x是否满足左右两格之内没有炮台 if((x&(x<<1))||(x&(x<<2)))return 0; int res=0; ///如果符合条件统计该情况下放了多少炮台 while(x){ res+=(x&1); x>>=1; } num[cnt]=res; return 1; } void init(){ ///初始化有多少个状态符合题意(每个点左右两格之内无炮台) cnt=0; for(int i=0;i<all;++i) if(judge(i)) state[cnt++]=i; } int main(){ int i,j,k,l; while(scanf("%d%d",&n,&m)!=EOF){ mst(pic,-1); ///-1在计算机中二进制表示为全1,,初始化这样做的好处当n为1时不用出错 mst(dp,0); ///因为pic[2]二进制全都为1,没有一个状态满足 all=1<<m; for(i=1;i<=n;++i){ pic[i]=0; scanf("%s",str); for(j=0;j<m;++j) pic[i]=pic[i]<<1|(str[j]=='P'?0:1); ///这里为0可以放炮台,为1不能放 } ans=0; init(); for(i=0;i<cnt;++i){ ///初始化第一行状态 if(pic[1]&state[i])continue; dp[1][i][0]=num[i]; ans=Max(ans,num[i]); /*****/ ///注意从这就要开始保存答案,不然会WA } for(i=0;i<cnt;++i){ ///第二行状态 if(pic[2]&state[i])continue; ///在这里体现出了初始化为-1的好处,当n==1时,不会错 for(j=0;j<cnt;++j){ if(pic[1]&state[j])continue; dp[2][i][j]=Max(dp[2][i][j],dp[1][j][0]+num[i]); ans=Max(ans,dp[2][i][j]); } } for(i=3;i<=n;++i){ for(j=0;j<cnt;++j){ ///第i行状态 if(pic[i]&state[j])continue; ///选取的state与pic冲突,不可取,下面同理 for(k=0;k<cnt;++k){///第i-1行状态 if(state[j]&state[k])continue; if(state[k]&pic[i-1])continue; for(l=0;l<cnt;++l){///第i-2行状态 if(state[l]&pic[i-2])continue; if(state[l]&state[k])continue; if(state[l]&state[j])continue; dp[i][j][k]=Max(dp[i][j][k],dp[i-1][k][l]+num[j]); ans=Max(ans,dp[i][j][k]); } } ///要dp数组的维度所表示的意义,i表示第几行,j表示在第i行选取的是状态state[j] } ///k表示i-1行选取的是state[k]状态,因为上面两行对当前行都会有影响 } ///所以更新状态时才会有那么多判断 printf("%d\n",ans); } return 0; }
相关文章推荐
- 蓝桥杯 历届试题 剪格子
- C++学习曲线
- REDIS CLUSTER简单安装配置
- 更换按钮的样式
- Java创建对象的四种方式
- HTML基础教程
- React框架入门
- Python 数据分析包:pandas 基础
- quartz mysql 表结构
- Latex排版全解
- 'Joe是这样背单词'第二步之——英语单词的分类处理
- Android中Intent的使用
- 蚂蚁感冒
- MyEclipse自动提示配置
- 笔试题50. LeetCode OJ (37)
- Spring的三种配置数据源的方式
- 【BZOJ 1455】罗马游戏
- 9.数据库服务器部署之------3步实现远程访问
- 初探Ajax
- Network(连通图割点)