hdu 2167 题解
Posted donkey2603089141
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 2167 题解相关的知识,希望对你有一定的参考价值。
题意
一个数字正方形(所有数都是两位的正整数),取了一个数后,它的周围 $ 8 $ 个数都不能被选,问最大取数总和。
注意数据范围 $ 3=< n <=15 $ 我们可能一开始会去想暴力搜索,枚举状态,但很容易发现时间复杂度过高过不去,于是可以去想dp,先预处理出可行状态,然后枚举可行状态,以及行数,进行转移即可。
我们定义 $ f[i][j] $ 表示当前在第 $ i $ 行此时状态为 $ j $ 状态先处理出来这里只要存编号就好了
转移方程 $ f[i][k]=max(f[i][k],f[i-1][j]+sum) $
$ sum (表示) k $行所有可以可以取出来的数的和( $ j $是 $ k $ 的上一行
还有一些判断可行的条件看代码吧
另外就是这一题的读入比较搞人,多试试就好了
代码
#include<bits/stdc++.h>
using namespace std;
int dp[16][1600],mape[16][16],sta[1600];
int n;
char s[100];
void star(){
n=0;
memset(dp,0,sizeof(dp));
memset(mape,0,sizeof(mape));
memset(sta,0,sizeof(sta));
}
void solve(){
int cnt=0;
for(int i=0;i<(1<<n);++i){
if((!(i&(i<<1)))&&(!(i&(i>>1)))) sta[++cnt]=i;
}
for(int i=1;i<=n;++i){//行数
for(int j=1;j<=cnt;++j){//上一行的状态
for(int k=1;k<=cnt;++k){//这一行的状态
if((!(sta[k]&sta[j]))&&(!(sta[k]&(sta[j]>>1)))&&(!(sta[k]&(sta[j]<<1)))){//保证不冲突
int sum=0;
for(int u=0;u<n;++u){
if(sta[k]&(1<<u)){//可以取数
sum+=mape[i][n-u-1];//这里是n-u-1,因为二进制第u位在图上是n-u-1位
}
dp[i][k]=max(dp[i][k],dp[i-1][j]+sum);
}
}
}
}
}
int ans=0;
for(int i=1;i<=cnt;i++) ans=max(ans,dp[n][i]);
printf("%d
",ans);
}
int main(){
while(gets(s)){
star();
int t=strlen(s);
for(int i=0;i<t;i+=3){
mape[1][n++]=(s[i]-'0')*10+(s[i+1]-'0');
}
for(int i=2;i<=n;++i){
for(int j=0;j<n;++j){
scanf("%d",&mape[i][j]);
}
}
solve();
getchar();getchar();
}
return 0;
}
以上是关于hdu 2167 题解的主要内容,如果未能解决你的问题,请参考以下文章