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;
}


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