题目:B - Free Candies
题意:
桌上有4堆糖果,每堆糖果高度不超过40,每颗糖果有一种颜色(一共20种,1,2,3...,20),
有一个篮子,一开始是空的,每当里面装有两颗颜色相同的糖果时,就可以从篮子里拿出这一对糖果。
如果篮子里的糖果数量为5个并且不能再拿时,篮子充满,游戏结束。问最多能拿走多少对糖果。
糖果堆上的所有糖果拿光了也算结束
思路:
dp[a][b][c][d]表示从第一堆取了a颗糖,第二堆取了b颗糖,第三堆取了c颗糖,第四堆取了d颗糖最多还能够获得多少对糖果。如果分别取a,b,c,d个,不论如何取,最后篮子中剩余的糖果颜色和个数都是一样的。所以可以把现在剩余的糖果的最多数量加上你之前取的那些糖果你能得到的糖果最多数量,就是要求的最多的糖果对数,那么一旦搜索到一个已经被搜索过得状态,直接返回即可,没必要继续搜索。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int mp[5][50],dp[50][50][50][50];
int n,top[5],book[25];
int dfs(int cnt,int book[])
{
if(dp[top[0]][top[1]][top[2]][top[3]]!=-1)
return dp[top[0]][top[1]][top[2]][top[3]];
if(cnt==5)
return dp[top[0]][top[1]][top[2]][top[3]]=0;
int num=0;
for(int i=0;i<4;i++)
{
if(top[i]==n)
continue;
int c=mp[i][top[i]];
top[i]+=1;
if(book[c])
{
book[c]=0;
num=max(num,dfs(cnt-1,book)+1);
book[c]=1;
}
else
{
book[c]=1;
num=max(num,dfs(cnt+1,book));
book[c]=0;
}
top[i]-=1;
}
return dp[top[0]][top[1]][top[2]][top[3]]=num;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(dp,-1,sizeof(dp));
memset(book,0,sizeof(book));
for(int i=0; i<n; i++)
for(int j=0; j<4; j++)
scanf("%d",&mp[j][i]);
top[0]=top[1]=top[2]=top[3]=0;
printf("%d\n",dfs(0,book));
}
return 0;
}