Pebbles HDU 2167

Pebbles HDU 2167

大意:给定一个N*N的方格,让你在里面取出一些数使其和最大,要求每一个数不能与其相邻的8个数同时取出.

思路:和炮兵阵地那一题有点像,但我们只需要考虑上一行的情况,这要简单很多,同时每一行的合法状态数量都是一样的,只需要每次读入预处理每一行每一种合法状态对应的和即可,转移方程很好写出。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
int a[16][16];
int state[1600];
int tot[15][1600];
int dp[16][1600];
int n,cot;
bool ok(int x){return (x & (x >> 1)) == 0;}
bool check(int now,int pre){
    return (now & pre) == 0 && (now & (pre >> 1)) == 0 && (now & (pre << 1)) == 0;
}
int getsum(int x,int now){
    int sum = 0;
    for(int i = 0;i < n;i++){
        if((now & (1 << i))){
            sum += a[x][i];
        }
    }
    return sum;
}
int main()
{
    //读入比较复杂
    while(~scanf("%d",&a[1][0])){
        char c;
        scanf("%c",&c);
        n = 0,cot = 0;
        while(c != '\n'){
            scanf("%d",&a[1][++n]);
            scanf("%c",&c);
        }
        n++;
        for(int i = 2;i <= n;i++){
            for(int j = 0;j < n;j++) {
                scanf("%d",&a[i][j]);
            }
        }
        //预处理合法状态
        for(int i = 0;i < (1 << n);i++){
            if(ok(i)) state[++cot] = i;
        }
        for(int i = 1;i <= cot;i++){
            for(int j = 1;j <= n;j++){
                //第j行的第i个状态对应的数字和
                tot[j][i] = getsum(j,state[i]);
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= cot;j++){
                int s1 =state[j];
                if(i == 1) {
                    dp[1][j] = tot[1][j];
                    continue;
                }
                for(int k = 1;k <= cot;k++){
                    int s2 =state[k];
                    if(check(s1,s2)){
                        dp[i][j] = max(dp[i][j],dp[i - 1][k] + tot[i][j]);
                    }
                }
            }
        }
        int ans = -1;
        for(int i = 1;i <= cot;i++){
            ans = max(ans,dp[n][i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}
上一篇:Codeforces 1333 E - Road to 1600 (构造)


下一篇:根据合同上的工资数如何计算你最后到手的工资