POJ 1185 HDU 4539 状态压缩DP
来源:互联网 发布:广州手机数据恢复 编辑:程序博客网 时间:2024/06/06 01:37
这两个题非常相似 画图出来的效果是;
POJ 1185
HDU 4539
dp[i][j][k] 表示第i行状态为j 第i-1行状态为k
转移方程为: dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+cnt[j])
确定本行放置是否合法 :
图1 X&(X<<1) X&(X<<2) 这2种情况为1了说明在这个炮兵距离为1 2处有另外的炮兵 状态不合法
图2 只需判断 X&(x<<2)是否为1
判断3行的兼容性:
图1 因为放置的炮兵都在同一列 所以 只用判断2个合法状态相与是否为1就可以了
图2 当前行 i 与i-1行 兼容的条件是 当前行 左移或右移 再与其相与是否合法 第i和i-2行 直接判断相与即可 如图所示
POJ 1185代码:
#include<stdio.h>#include<math.h>#include<string.h>#include<algorithm>#include<stdlib.h>#include<math.h>using namespace std;#define maxn 110#define inf 10000007typedef long long ll;int n,m;char str[110]; //存初始图int dp[110][70][70]; //dp[[i][j][k]int statu[110]; //初始每行的状态int legal[110]; //合法状态int cnt[70]; //每个合法状态中二进制中1的个数int num; //多少个合法状态,枚举出来void init() //初始化,读入图{ int i,j; memset(statu,0,sizeof(statu)); for(i=0;i<n;i++) { scanf("%s",str); for(j=0;j<m;j++) { if(str[j]=='H') statu[i]=(statu[i]<<1)|1; else statu[i]=statu[i]<<1; } }} int count_one(int x) //求X二进制中1的个数 { int count=0; while(x) { count++; x=x&(x-1); } return count;}bool ok(int x) //判断状态是否合法{ if(x&(x<<1)) return 0; if(x&(x<<2)) return 0; return 1;}void count_stu() //枚举出一行中所有合法的摆放状态{ num=0; int total=1<<m; for(int i=0;i<total;i++) { if(ok(i)) { legal[num]=i; cnt[num++]=count_one(i); } }}void Dp() //dp转移,求出最终结果{ int i,j,k,l; memset(dp,-1,sizeof(dp)); for(i=0;i<num;i++) //初始化DP数组 { if(statu[0]&legal[i]) continue; //枚举每个合法状态与初始状态是否冲突 dp[0][i][0]=cnt[i]; } for(i=1;i<n;i++){ for(j=0;j<num;j++){ if(legal[j]&statu[i]) continue; //枚举当前行每个合法状态与初始状态是否冲突 for(k=0;k<num;k++){ if(legal[j]&legal[k]) continue; //当前行与上一行是否冲突 for(l=0;l<num;l++){ if(legal[j]&legal[l]) continue; //当前行与上上一行是否冲突 if(dp[i-1][k][l]==-1) continue; dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+cnt[j]); } } } }}void print() //打印输出,找出到达状态n-1时最大的值{ int i,j; int ans=0; for(i=0;i<num;i++) for(j=0;j<num;j++) ans=max(ans,dp[n-1][i][j]); printf("%d\n",ans);}int main(){ freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m)==2) { init(); count_stu(); Dp(); print(); } return 0;}
HDU 4539 代码
#include<stdio.h>#include<math.h>#include<string.h>#include<algorithm>#include<stdlib.h>#include<math.h>using namespace std;#define maxn 110#define inf 10000007typedef long long ll;int n,m;//char str[110];int dp[110][200][200];int statu[110];int legal[200];int cnt[200];int num;void init(){ int i,j; memset(statu,0,sizeof(statu)); int tmp; for(i=0;i<n;i++) { for(j=0;j<m;j++) { scanf("%d",&tmp); if(tmp==0) statu[i]=(statu[i]<<1)|1; else statu[i]=statu[i]<<1; } }}int count_one(int x){ int count=0; while(x) { count++; x=x&(x-1); } return count;}bool ok(int x){ // if(x&(x<<1)) return 0; if(x&(x<<2)) return 0; //这里变化了 return 1;}void count_stu(){ num=0; int total=1<<m; for(int i=0;i<total;i++) { if(ok(i)) { legal[num]=i; cnt[num++]=count_one(i); } } // printf("%d\n",num);}void Dp(){ int i,j,k,l; memset(dp,-1,sizeof(dp)); for(i=0;i<num;i++) { if(statu[0]&legal[i]) continue; dp[0][i][0]=cnt[i]; } for(i=1;i<n;i++){ for(j=0;j<num;j++){ if(legal[j]&statu[i]) continue; for(k=0;k<num;k++){ if((legal[j]<<1)&legal[k]) continue; //当前行左移与上一行 if((legal[j]>>1)&legal[k]) continue; //当前行右移与上一行 for(l=0;l<num;l++){ if((legal[k]<<1)&legal[l]) continue; //上一行左移与上上一行 if((legal[k]>>1)&legal[l]) continue; //上一行右移与上上一行 if(legal[j]&legal[l]) continue; //当前行与上上一行 if(dp[i-1][k][l]==-1) continue; dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+cnt[j]); } } } }}void print(){ int i,j; int ans=0; for(i=0;i<num;i++) for(j=0;j<num;j++) ans=max(ans,dp[n-1][i][j]); printf("%d\n",ans);}int main(){ freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m)==2) { init(); count_stu(); Dp(); print(); } return 0;}
- POJ 1185 HDU 4539 状态压缩DP
- 【状态压缩DP】POJ 1185
- poj 1185(状态压缩dp)
- poj 1185 状态压缩DP
- POJ 1185 状态压缩DP
- poj 1185 状态压缩DP
- poj 1185 状态压缩dp
- POJ 1185 状态压缩DP
- poj 1185(状态压缩dp)
- POJ 1185 状态压缩DP
- POJ 1185 状态压缩DP
- [状态压缩DP] POJ 1185
- hdu 4539 状态压缩DP
- hdu 4539 状态压缩DP
- hdu 4539 状态压缩DP
- [状态压缩DP] HDU 4539
- [状态压缩DP] Poj 3254, Poj 1185
- POJ 3254 & POJ 1185 (状态压缩DP)
- android动态添加组件
- 美国:颠覆了的概念
- RTF 换行与中文显示
- 手机进入巨屏时代
- 堆和栈的区别。
- POJ 1185 HDU 4539 状态压缩DP
- 提高web性能之--压缩组件
- 读取系统资源函数getResources()
- sqlserver游标
- DSP例程结构
- 两个线程A和B, A打印1, 3, ..., 99, B打印2, 4, ..., 100, 要求A和B严格交替打印(Java实现)
- 项目四--学生类Student
- 28xx 系列dsp c/c++编程入门
- 《程序员的第一年》---------- 能省一句代码就省一句【附带正则表达式知识】