Tourism Planning(HDU 4049状压dp)

题意:n个朋友去游览m个城市,给出每个人对每个城市的兴趣值,和每人去每个城市的花费,如果两人在一个城市有一个价值,若多于2人这这个价值是任意两人产生价值的总和。在去每个城市的过程中人可以随便离开,也可以一个城市也不游览,求兴趣值总和+产生价值总和-总花费 最大。

分析:开始读错题意了,白白浪费了一个小时,吸取教训啊。。。

理解题意后分析状态,dp[i][j]在去第i个城市情况为j(0没去,1去了)的最大值,先预处理一下所有可能情况的求兴趣值总和、产生价值总、花费 (记人数)。

#include <map>

#include <set>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <cstdio>

#include <vector>

#include <string>

#include <cctype>

#include <complex>

#include <cassert>

#include <utility>

#include <cstring>

#include <cstdlib>

#include <iostream>

#include <algorithm>

using namespace std;

typedef pair<int,int> PII;

typedef long long ll;

#define lson l,m,rt<<1

#define pi acos(-1.0)

#define rson m+1,r,rt<<11

#define All 1,N,1

#define read freopen("in.txt", "r", stdin)

#define N 1<<11

#define INF 100000000

const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;

const int mod =  1000000007;

int dp[15][N],t[15][N],v[15][15],B[15][15],b[N],num[N],n,m,p[15];

void init(){

    memset(num,0,sizeof(num));

    memset(b,0,sizeof(b));

    memset(t,0,sizeof(t));

    int cas=(1<<n);

    for(int i=0;i<m;++i)

        for(int s=1;s<cas;++s)

            for(int j=0;j<n;++j)

            if(s&(1<<j))

            t[i][s]+=v[j][i];

    for(int s=1;s<cas;++s){

        for(int i=0;i<n;++i)

        if(s&(1<<i)){

            num[s]++;

            for(int j=i+1;j<n;++j)

                if(s&(1<<j))

                b[s]+=B[i][j];

        }

    }

}

void solve(){

    init();

     int cas=(1<<n),maxx;

    for(int i=0;i<m;++i)

        for(int j=0;j<cas;++j)

        dp[i][j]=-INF;

        dp[0][0]=0;

    for(int i=1;i<cas;++i){

        dp[0][i]=t[0][i]+b[i]-p[0]*num[i];

        //cout<<t[0][i]<<" "<<b[i]<<" "<<num[i]<<endl;

    }

        for(int i=1;i<=m;++i){

        maxx=-INF;

        for(int j=0;j<cas;++j){

            if(i==m&&j>0)continue;

            int maxv=-INF;

        for(int k=j;k<cas;++k)

        //判断j是k的子集

        if((k&j)==j){

            maxv=max(maxv,dp[i-1][k]);

        }

        dp[i][j]=maxv+t[i][j]+b[j]-p[i]*num[j];

        }

        maxx=max(maxx,dp[i][0]);

        }

        if(maxx>0)printf("%d\n",maxx);

        else printf("STAY HOME\n");

}

int main()

{

    while(~scanf("%d%d",&n,&m)){

        if(n==0&&m==0)break;

        for(int i=0;i<m;++i)

        scanf("%d",&p[i]);

        for(int i=0;i<n;++i)

            for(int j=0;j<m;++j)

            scanf("%d",&v[i][j]);

        for(int i=0;i<n;++i)

            for(int j=0;j<n;++j)

            scanf("%d",&B[i][j]);

        solve();

    }

return 0;

}

        

  

 

你可能感兴趣的:(HDU)