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 题解的主要内容,如果未能解决你的问题,请参考以下文章

HDU_2167_状态压缩dp

Pebbles(hdu 2167)

HDU2167(SummerTrainingDay02-D 状态压缩dp)

HDU2167 Pebbles(状压DP)

HDU 2167 状压dp方格取数

hdu 2167 方格取数 状压dp(经典)