标签:
Time Limit: 20 Sec Memory Limit: 256 MB
http://acm.hdu.edu.cn/showproblem.php?pid=4111
The first line contains an integer T(1 <= T <= 4000), indicating the number of test cases.
Each test case contains several lines.
The first line contains an integer N(1 <= N <= 50).
The next line contains N positive integers A1 ....AN(1 <= Ai <= 1000), represents the numbers they write down at the beginning of the game.
Output
For each test case in the input, print one line: "Case #X: Y", where X is the test case number (starting with 1) and Y is either "Alice" or "Bob".
Case #1: Alice Case #2: Bob Case #3: Bob
题意
给你n堆石头,你有两个选择,1.减少一堆石头数量1,2.合并两堆石头
如果遇到不能操作的情况就算输
题解:
这道题当成dp来做,dp[i][j]表示现在有i堆只有1个,j表示现在我能够操作次数
操作次数等于 sigma(a[i])-n+1,其中a[i]>1,n为满足条件的a[i]的个数
------------------------
那么转移方程就出来了,1个的,要么消去,要么和1个的合并,要么和多个的合并
然后就可以记忆化搜索搞了
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 50051 #define mod 10007 #define eps 1e-9 int Num; char CH[20]; //const int inf=0x7fffffff; //нчоч╢С const int inf=0x3f3f3f3f; /* inline void P(int x) { Num=0;if(!x){putchar(‘0‘);puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } */ inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } inline void P(int x) { Num=0;if(!x){putchar(‘0‘);puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } //************************************************************************************** int dp[100][maxn]; int a[maxn]; int dfs(int a,int b)//a 表示还有多少组为1 b表示还剩下多少次操作次数 { if(dp[a][b]!=-1) return dp[a][b]; dp[a][b]=0;//其他情况都是不可操作的 if(b==1) return dp[a][b]=dfs(a+1,0);//只剩一个单独的一,加入其它1中 if(a>=1&&!dfs(a-1,b))//直接去掉一个1 dp[a][b]=1; if(a>=1&&b&&!dfs(a-1,b+1))//将一个1合到其它数中 dp[a][b]=1; if(a>=2&&((b&&!dfs(a-2,b+3))||(b==0&&!dfs(a-2,2))))//将2个1并起来 dp[a][b]=1; if(b>=2&&!dfs(a,b-1))//减小一 dp[a][b]=1; return dp[a][b]; } int main() { //freopen("test.txt","r",stdin); memset(dp,-1,sizeof(dp)); int t=read(); for(int cas=1;cas<=t;cas++) { int flag=0; int sum=0; int n=read(); for(int i=0;i<n;i++) { a[i]=read(); if(a[i]==1) flag++; else sum+=a[i]+1; } sum--; dfs(flag,sum); if(dp[flag][sum]) printf("Case #%d: Alice\n",cas); else printf("Case #%d: Bob\n",cas); } }
hdu 4111 Alice and Bob 记忆化搜索 博弈论
标签:
原文地址:http://www.cnblogs.com/qscqesze/p/4521254.html