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

  

 

posted on 2015-07-24 20:03  积跬步、至千里  阅读(203)  评论(0编辑  收藏  举报

导航