您的位置:首页 > 其它

HDU4778 Gems Fight!(记忆化搜索+博弈)

2015-10-13 22:22 190 查看
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4778

题目大意:有B个包裹,里面有各种颜色的GEM,共有G个颜色。Alice和Bob轮流挑选包裹放到一个地方,如果挑选出来的同种颜色的GEM超过S个,当前回合者可以得分,每超过S个得一分。如果在回合内得分了,可以额外进行一个回合。问Alice的得分减去Bob的得分最大是多少。

#include<iostream>
#include<algorithm>
#include<string>
#include<map>//ll dx[4]={0,0,-1,1};ll dy[4]={-1,1,0,0};
#include<set>//
#include<vector>
#include<cmath>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define mod 1e9+7
#define ll long long
using namespace std;
#define REP(i,n) for(int i=0;i<(n);++i)
struct node {
int c[10]; //一个包里某颜色个数
}Bag[30];
int b,g,s,now[10],sg[1<<22];
int judge(int k){
int total = 0;
REP(i,g+1){
now[i]+=Bag[k].c[i];
total+=now[i]/s; //每超过s个得一分
now[i]%=s; //该颜色(i)剩下的个数
}
return total; //返回得到的分数
}
int dfs(int dp){
if(sg[dp] != -1)
return sg[dp];
int tep[10],ans = -100000000; //结果有可能是负的
for(int i=1;i<=g;++i)
tep[i] = now[i]; //now[i]表示现在第i种颜色的有几个了
for(int i=0;i<b;++i){ //遍历背包
int k = 1 << i;
if(!(dp & k)){ //dp这个状态里第k个包没取
int total = judge(i); //判断当前这个人能得多少分
if(total > 0) //得分了
ans = max(ans,total + dfs(dp|k)); //下一轮还是自己选 ,dp|k表示算取了第k个包
else
ans = max(ans,total - dfs(dp|k)); //下一轮对方选
for(int j=1;j<=g;++j)
now[j] = tep[j]; //注意,每进行一次上面的dfs,now[]值会变
}
}
return sg[dp] = ans;
}

void init() {
int k = 1 << b;
memset(sg,-1,sizeof(sg));
sg[k-1] = 0; //记忆化搜索最终状态,所有包都取完
memset(now,0,sizeof(now));
memset(Bag,0,sizeof(Bag));
}
int main() {
int n,m,t,cs=0;
while(~scanf("%d%d%d",&g,&b,&s)) { //颜色数、包裹数、回合数
if(!b && !g && !s)
break;
init();
REP(i,b){
scanf("%d",&n); //第i个包裹里有n种颜色
while(n--){
scanf("%d",&m); //颜色编号
Bag[i].c[m]++;
}
}
printf("%d\n",dfs(0)); //0表示一个包都没取的状态
}
return 0;
}
#include<iostream>
#include<algorithm>
#include<string>
#include<map>//int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};
#include<set>//
#include<vector>
#include<cmath>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define mod 1e9+7
#define ll long long
using namespace std;
struct node{
int c[10];
}x[30];
int g,b,k,m,a;
int now[30];
int dp[(1<<22)];
int ss;
int dfs(int p){
if(dp[p]!=-1)
return dp[p];
int tmp[10]; //注意是内部函数,需要定义在里面
for(int i=1;i<=g;++i){
tmp[i]=now[i];
}
int ss=-10000000;
for(int i=0;i<b;++i){
if(p&(1<<i))
continue;
int cnt=0;
for(int j=1;j<=g;++j){
now[j]+=x[i].c[j];
cnt+=now[j]/k;
now[j]%=k;
}
if(cnt>0)
ss=max(ss,cnt+dfs(p|(1<<i)));
else
ss=max(ss,cnt-dfs(p|(1<<i)));
for(int j=1;j<=g;++j)
now[j]=tmp[j];
}
dp[p]=ss;
return dp[p];
}
int main(){
while(cin>>g>>b>>k){
if(g+b+k==0)
break;
memset(x,0,sizeof(x));
memset(now,0,sizeof(now));
for(int i=0;i<b;++i){
cin>>m;
for(int j=0;j<m;++j){
cin>>a;
x[i].c[a]++;
}
}
memset(dp,-1,sizeof(dp));
dp[(1<<b)-1]=0;
cout<<dfs(0)<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: