nyoj85——炮兵阵地——————【状态压缩、动态规划】
2015-01-31 13:07
288 查看
/**
结题思路:用dp[r][i][j]表示第r行r行状态为i,r-1行状态为j时的最大可部署炮兵的个数。通过求解合法状态,缩小需要遍历的状态范围。同时求出各个合法状态的二进制中1的个数,然后特殊处理首行,然后dp求解每行每种可行状态对应的可部兵的最大个数。状态转移方程dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+num_1[i])。
*/
结题思路:用dp[r][i][j]表示第r行r行状态为i,r-1行状态为j时的最大可部署炮兵的个数。通过求解合法状态,缩小需要遍历的状态范围。同时求出各个合法状态的二进制中1的个数,然后特殊处理首行,然后dp求解每行每种可行状态对应的可部兵的最大个数。状态转移方程dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+num_1[i])。
*/
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> using namespace std; int n,m,top,num_legal; char Map[110][15]; int dp[105][1<<6][1<<6]; //dp[r][i][j]表示第r行的状态为i,第r-1行的状态为j时的最多放的炮兵数 //可以发现虽然m值最大是10,但是合法的状态值最多60个 int an_Map[110];//将每行的图用状态值表示0代表原图为P,1代表H int legal[1<<6];//将合法的状态放入数组,即不会互相攻击的状态 int num_1[1<<6];//记录每个合法状态值得二进制中1的个数 int max(int x,int y){ return x>y?x:y; } bool jud_legal(int x){ //相邻或只隔了一个位置为非法,相隔两个位置为合法 if(x&(x<<1))return false; if(x&(x<<2))return false; return true; } int get_num(int x){ //得到x的二进制中1的个数 int tmp_num=0; while(x){ if(1&x) tmp_num++; x>>=1; } return tmp_num; } void solve_legal(){ top=1<<m; //合法状态的最大值 num_legal=0; //合法状态的个数 for(int i=0;i<top;i++){ if(jud_legal(i)){ //判断该状态是否合法 legal[num_legal]=i; num_1[num_legal++]=get_num(i); } } } void init(){ memset(dp,-1,sizeof(dp)); //初始化为-1表示不可部兵 memset(an_Map,0,sizeof(an_Map)); memset(legal,0,sizeof(legal)); memset(num_1,0,sizeof(num_1)); } void solve_Map(){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(Map[i][j]=='H'){ an_Map[i]+=(1<<(m-j)); //将原图的每行都用一个数值表示图状态 } } } } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); if(n==0||m==0){ printf("%d\n",0); continue; } init(); getchar(); for(int i=1;i<=n;i++){ gets(Map[i]+1); } solve_legal(); //处理出合法状态的数组 solve_Map(); //处理出图的数字化表示数组 for(int j=0;j<num_legal;j++){ //将第一行做特殊处理 if((an_Map[1]&legal[j])==0){//如首行图不与该合法状态冲突 //将该合法状态可部兵数赋给首行对应状态的dp数组 //0行状态为0不会对下面的情况产生影响 dp[1][j][0]=num_1[j]; } } for(int r=2;r<=n;r++){ for(int i=0;i<num_legal;i++){ if(legal[i]&an_Map[r]) //r行合法状态与r行图冲突 continue; for( int j=0;j<num_legal;j++){ if(legal[i]&legal[j])continue;//r行合法状态与r-1行合法状态冲突 for(int k=0;k<num_legal;k++){ if(legal[k]&legal[i])continue;//r-2行合法状态和r行合法状态冲突 if(legal[k]&legal[j])continue;//r-2行合法状态和r-1行合法状态冲突 if(dp[r-1][j][k]==-1)continue; //可以不加本语句。没更新过,不会对该dp值的最大值产生影响 dp[r][i][j]=max(dp[r][i][j],dp[r-1][j][k]+num_1[i]); } } } } int ans=-1; for(int j=0;j<num_legal;j++){ for(int k=0;k<num_legal;k++){ //遍历所有状态求出最值 ans=max(ans,dp [j][k]); } } printf("%d\n",ans); } return 0; }
相关文章推荐
- 状态压缩动态规划(压缩状态DP)学习笔记
- POJ_3420_Quad Tiling_搜索,矩阵快速幂,状态压缩,动态规划
- hihocoder 1044 动态规划 状态压缩
- CODEVS_2800 送外卖 状态压缩+动态规划
- [ACM_动态规划] 轮廓线动态规划——铺放骨牌(状态压缩1)
- 【状态压缩】【动态规划】坑爹题
- 状态压缩动态规划
- 【BZOJ1087】【SCOI2005】互不侵犯King 状态压缩 动态规划 水题 都不用加特技
- 动态规划——状态压缩入门级
- 【NOI2001】炮兵阵地(状态压缩,动态规划)
- 状态压缩 - 动态规划 - LightOJ - 1011 - Marriage Ceremonies
- ZOJ-3697 Bad-written Number 恶心模拟-状态压缩-动态规划
- HDU——1074 Doing homework (动态规划——状态压缩)
- 【jzoj5251】【GDOI2018模拟8.11】【决战】【状态压缩动态规划】
- CODEVS_2800 送外卖 状态压缩+动态规划
- POJ 3254 Corn Fields [动态规划 简单状态压缩]
- POJ-1185 炮兵阵地 动态规划+状态压缩
- 状态压缩动态规划总结
- Poj 2923 Relocation(状态压缩+动态规划)
- HDU 1565 方格取数(1) HDU 2167 Pebbles 基础状态压缩动态规划