hdu5691--Sitting in Line(狀壓DP,2016百度之星Round2A/1002)

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=5691


分析:看到N的範圍,八成就是狀壓。q[i]表示第i個位置填第幾個數。

          狀態:dp[i][j]表示用了i這種情況裏這些數,從左往右填以j爲結尾的最大值。

          狀態轉移方程:當第k個位置已經被固定填什麼數時,向狀態st裏添加i並以i爲結尾,dp[st|(1<<q[k])][q[k]] = max(dp[st|(1<<q[k])][q[k]], dp[st][j]+a[j]*a[q[k]])。當第k位置不固定,枚舉各個數,該數不在集合時,便添加到集合裏,dp[st|(1<<i)][i] = max(dp[st|(1<<i)][i], dp[st][j]+a[j]*a[i])。


代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
const int N = 20;
const ll INF = 1LL<<50;
ll dp[1<<N][N];
int p[N], q[N], a[N];

int main() {
    int T, n;
    scanf("%d", &T);
    for(int kase = 1; kase <= T; kase++) {
        scanf("%d", &n);

        memset(q, -1, sizeof(q));
        for(int i = 0; i < n; i++) {
            scanf("%d%d", &a[i], &p[i]);
            if(p[i] >= 0) q[p[i]] = i;
        }
        for(int i = 0; i < (1<<n); i++)
            for(int j = 0; j < n; j++)
                dp[i][j] = -INF;
        if(~q[0]) dp[1<<q[0]][q[0]] = 0;
        else {
            for(int i = 0; i < n; i++)
                dp[1<<i][i] = 0;
        }
        for(int st = 1; st < (1<<n); st++) {
            int k = 0;
            for(int i = 0; i < n; i++)
                k += st>>i&1;
            if(~q[k]) {
                if(st & (1<<q[k])) continue;
                for(int j = 0; j < n; j++) {
                    if(~st&(1<<j)) continue;
                    dp[st|(1<<q[k])][q[k]] = max(dp[st|(1<<q[k])][q[k]], dp[st][j]+a[j]*a[q[k]]);
                }
            }
            else {
                for(int i = 0; i < n; i++) {
                    if(st & (1<<i)) continue;
                    for(int j = 0; j < n; j++) {
                        if(~st&(1<<j)) continue;
                        dp[st|(1<<i)][i] = max(dp[st|(1<<i)][i], dp[st][j]+a[j]*a[i]);
                    }
                }
            }
        }
        ll ans = -INF;
        for(int i = 0; i < n; i++)
            ans = max(ans, dp[(1<<n)-1][i]);
        printf("Case #%d:\n%I64d\n", kase, ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章