Free Candies
题链接 https://vjudge.net/contest/241993#problem/B
题意:有四堆糖果,每堆糖果有n个,有一个篮子,最多只能装5个糖果,每次从任意一堆堆顶拿走一个糖果,如果篮子里有俩个 相同的糖果,那么可以被自己收下,看看最多能收下几对糖果
题解:这道题用记忆化搜索,定义一个dp的四维数组代表每堆糖果分别被拿了a,b,c,d个糖果时最多拿走的糖果对数,定义 d【4】数组,d【0】d【1】d【2】d【3】分别代表每堆糖果已经被拿走的糖果数,定义book数组标记糖果,如果某个 糖果被 放进篮子里,那么标记为1。
代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int dp[100][100][100][100];
int s[4][100],book[100],h[4],n;
int dfs(int x)
{
if(dp[h[0]][h[1]][h[2]][h[3]]!=-1) //该状态被搜过 ,返回
return dp[h[0]][h[1]][h[2]][h[3]];
if(x==5) //篮子里的五个糖果不一样,退出
return dp[h[0]][h[1]][h[2]][h[3]]=0;
int sum=0;
for(int i=0;i<4;i++)
{
if(h[i]==n) //这堆已被拿完
continue;
int k=s[i][h[i]];
h[i]++;
if(book[k]) //表示篮子里有一样的
{
book[k]=0;
sum=max(sum,dfs(x-1)+1); //拿出,对数加1
book[k]=1;
}
else //篮子里没有一样的
{
book[k]=1;
sum=max(sum,dfs(x+1));
book[k]=0;
}
h[i]--; //回溯
}
return dp[h[0]][h[1]][h[2]][h[3]]=sum;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(h,0,sizeof(h));
memset(dp,-1,sizeof(dp));
memset(book,0,sizeof(book));
int i,j;
for( i=0;i<n;i++)
for( j=0;j<4;j++)
scanf("%d",&s[j][i]);
printf("%d\n",dfs(0));
}
}