目大意:给定一个N*N的方格,让你在里面取出一些数使其和最大,要求每一个数不能与其相邻的8个数同时取出~~ 状态转移方程: dp[i][j]=max(dp[i-1][k]+sum[i][j]); 第i行第j个状态 最大取值和
/* 目大意:给定一个N*N的方格,让你在里面取出一些数使其和最大,要求每一个数不能与其相邻的8个数同时取出~~ 状态转移方程: dp[i][j]=max(dp[i-1][k]+sum[i][j]); 第i行第j个状态 最大取值和 */ #include<iostream> #include<algorithm> #include<cstdio> #include<memory.h> using namespace std; int dp[22][1<<15]; int cnt; int sum[22][1<<15];///合法状态的数和 int s[1<<15];///合法的状态被保存在这里 int b[22]; int n,a[22][22]; char str[101]; void init() { b[0]=1; for(int i=1;i<16;i++) b[i]=b[i-1]<<1; } void DP() { int i,j,k,t,len=1<<n; cnt=0; memset(dp,0,sizeof(dp)); memset(sum,0,sizeof(sum)); for(i=0;i<len;i++) { if((i<<1)&i) continue; s[cnt++]=i; } for(i=0;i<n;i++) { for(j=0;j<cnt;j++) { for(k=0;k<n;k++) { if(b[k]&s[j]) sum[i][j]+=a[i][k]; } } } for(i=0;i<cnt;i++) dp[0][i]=sum[0][i]; for(i=1;i<n;i++) { for(j=0;j<cnt;j++) { for(k=0;k<cnt;k++)//前一行 状态 { if(s[j]&s[k]) continue; if(s[j]&(s[k]<<1)) continue; if(s[j]&(s[k]>>1)) continue; dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[i][j]); } } } int res=0; for(i=0;i<cnt;i++) res=max(res,dp[n-1][i]); cout<<res<<endl; } int main() { int len; init(); while(gets(str)) { len=strlen(str); n=0; for(int i=0; i<len; i+=3) { a[0][n++]=(str[i]-'0')*10+(str[i+1]-'0'); } for(int i=1; i<n; i++) { int m=0; gets(str); for(int j=0; j<len; j+=3) a[i][m++]=(str[j]-'0')*10+(str[j+1]-'0'); } DP(); getchar(); } return 0; }
hdu 2167 状态压缩dp(入门题目)
最新推荐文章于 2021-07-21 16:12:16 发布