HDU4049【狀壓DP】

這個題真的是水,但是題意有點迷。。。

旅遊順序已經定了,按順序
然後如果一個人要旅遊下一個景點,中途景點也要走。
否則,他將離隊,不再旅游下去/
N<=10, M<=10


思路:
狀壓遊客的組合,預處理出組合的額外值,人數。
然後依次枚舉景點,枚舉前一個景點的人數組合,然後更新當前景點的人數組合,因爲人數組合總是會變少。
然後每次取大就好啦,中間可能有負數!但是不影響總的!

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long LL;
#define mem(a, b) memset(a, b, sizeof(a))

const int INF = 0x3f3f3f3f;
int cost[20], ins[20][20], ma[20][20];
int dp[20][1<<15];
int val[1<<15];
int preval[15][1<<15];
int num[1<<15];
int n,m;

void init()
{
    vector<int> a;
    int up = (1<<n)-1;
    for(int i = 0; i <= up; i++)
    {
        a.clear();

        for(int j = 0; j < n; j++){
            if(i&(1<<j))
                a.push_back(j);
        }

        int ans = 0;
        int len = (int)a.size();
        for(int j = 0; j < len; j++)
        {
            for(int k = j+1; k < len; k++)
                ans += ma[a[j]][a[k]];
        }
        val[i] = ans;
        num[i] = len;
    }

    for(int i=1;i<=m;i++){
        for(int j=0;j<=up;j++)
        {
            int temp = 0;
            for(int k=0;k<n;k++)
                if(j & (1<<k)) temp += ins[k][i];
            preval[i][j] = temp;
        }
    }
}

int Mmax(int x, int y){
    return x>y?x:y;
}

void solve()
{
    mem(dp, -INF);
    mem(dp[0], 0);
    int up = (1<<n)-1;
    for(int i = 1; i <= m; i++){
        for(int j = 0; j <= up; j++){
            int aim;
            int x = j;
            dp[i][0] = Mmax(dp[i][0], dp[i-1][j]);
            for(int k = x ; k > 0 ; k = (k - 1) & x)
            {
                aim = k;
                dp[i][aim] = Mmax(dp[i][aim],dp[i-1][j]+val[aim]+preval[i][aim]-cost[i]*num[aim]);
            }
        }
    }

    int mx = 0;
    for(int i = 0; i <= up; i++)
        mx = max(mx, dp[m][i]);
    if(mx == 0){
        puts("STAY HOME");
        return;
    }
    printf("%d\n",mx);

}

int main()
{
    int T;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m) break;

        for(int i = 1; i <= m; i++)
            scanf("%d",&cost[i]);

        for(int i = 0; i < n; i++)
            for(int j = 1; j <= m; j++)
                scanf("%d",&ins[i][j]);

        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                scanf("%d",&ma[i][j]);
        init();
        solve();
    }

    return 0;
}
發佈了799 篇原創文章 · 獲贊 125 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章