您的位置:首页 > 其它

HDU 4778 Gems Fight!

2014-01-19 23:36 381 查看
杭州区域赛的题目

题意:

B个包,里面有不同数量和颜色的宝石。每轮,Alice或Bob选一个未选过的包,把包里的宝石倒入熔炉中。如果熔炉中同种颜色的>=S个,那么每S个会合成一个魔法石。魔法石给当前操作的人,同时此人可以继续操作一轮。他们都需要获得尽可能多的魔法石,两人操作都最佳,求A-B。

思路:

dp[state] 表示当前操作的人-后手的最大差值 ,state表示选包的情况,1表示可选,0表示已选。

枚举状态,再枚举选包。假设选第i个包,求出此时能获得魔法石的数量,如果大于0说明后手还是自己。

如果后手是自己,那么就+dp[(1<<i)^st]

否则-dp[(1<<i)^st];

code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
    
#define N  200010
#define ll long long
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int MOD   =1000000007;
const double EPS=1e-7;

int c[32][16];
int dp[1<<21];
int cnt[16],tmp[16];
int G,B,S;

int cal(int st){
    for(int i=0;i<B;i++) if(1<<i&st){
        for(int j=0;~c[i][j];j++) cnt[c[i][j]]++;
    }
    int ans=0;
    for(int i=0;i<=G;i++) ans+=cnt[i]/S,cnt[i]%=S; 
    return ans;
}

int main(){
    while(~scanf("%d%d%d",&G,&B,&S),G||B||S){
        CLR(cnt,0);
        for(int i=0;i<B;i++){
            int n;
            scanf("%d",&n);
            for(int j=0;j<n;j++) scanf("%d",&c[i][j]);
            c[i]
=-1;
        }
        int M=1<<B;
        for(int st=1;st<M;st++){
            dp[st]=-INF;
            CLR(cnt,0);
            cal((M-1)^st);
            memcpy(tmp,cnt,sizeof(cnt));
            for(int i=0;i<B;i++) if(1<<i&st){
                memcpy(cnt,tmp,sizeof(cnt));
                int bonus=cal(1<<i);
                if(bonus) dp[st]=max(dp[st],dp[1<<i^st]+bonus);
                else dp[st]=max(dp[st],-dp[1<<i^st]);
            }
        }
        printf("%d\n",dp[M-1]);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: