HDU 1565 方格取数(1)(状态压缩DP)

题目链接:HDU 1565 方格取数(1)

挺简单的一个状压DP,因为一点小失误搞了好久。。

先按最大值跑一遍getState可以知道一行可以有多少种状态,就是MAX_K。状态转移方程:dp[s][i] = max(dp[s][i], dp[j][i - 1] + getSum(state[s], i)),dp[s][i]表示第i行在状态state[s]下可以取到的前i行的最大值。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAX_N = 20;
const int MAX_S = (1 << MAX_N) + 100;
const int MAX_M = MAX_N + 5;
const int MAX_K = 17745 + 1000;

int dp[MAX_K][MAX_M];
int _map[MAX_M][MAX_M];
int state[MAX_K];
int n, cnt;

bool is_ok(int s)
{
    if(s & (s << 1))
        return false;
    return true;
}

int getSum(int s, int i)
{
    int res = 0;
    int k = 0;
    while(s > 0)
    {
        if(s & 1)
            res += _map[i][k];
        s = s >> 1;
        k++;
    }
    return res;
}
int getState()
{
    cnt = 0;
    int len = (1 << n) - 1;
    for(int s = 0; s <= len; s++)
        if(is_ok(s))
            state[cnt++] = s;
    return cnt;
}
int main()
{
    //freopen("in.txt", "r", stdin);
    while(scanf("%d", &n) != EOF)
    {
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                scanf("%d", &_map[i][j]);
        getState();
        int _max = 0;
        for(int s = 0; s < cnt; s++)
            dp[s][0] = getSum(state[s], 0);
        for(int i = 1; i < n; i++)
        {
            for(int s = 0; s < cnt; s++)
            {
                for(int j = 0; j < cnt; j++)
                {
                    if(state[s] & state[j])
                        continue;
                    dp[s][i] = max(dp[s][i], dp[j][i - 1] + getSum(state[s], i));
                }
            }
        }
        for(int s = 0; s < cnt; s++)
            _max = max(_max, dp[s][n - 1]);
        printf("%d\n", _max);
    }
    return 0;
}



你可能感兴趣的:(HDU 1565 方格取数(1)(状态压缩DP))