题意:有四堆糖果,每堆糖果有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 a[4][100];
int book[100];
int d[4],n;
int dfs(int t)
{
if(dp[d[0]][d[1]][d[2]][d[3]]!=-1) //该状态被搜过 ,返回
return dp[d[0]][d[1]][d[2]][d[3]];
if(t==5) //篮子里的五个糖果不一样,退出
return dp[d[0]][d[1]][d[2]][d[3]]=0;
int ans=0;
for(int i=0;i<4;i++)
{
if(d[i]==n) //这堆已被拿完
continue;
int k=a[i][d[i]];
d[i]++;
if(book[k]) //表示篮子里有一样的
{
book[k]=0;
ans=max(ans,dfs(t-1)+1); //拿出,对数加1
book[k]=1;
}
else //篮子里没有一样的
{
book[k]=1;
ans=max(ans,dfs(t+1));
book[k]=0;
}
d[i]--; //回溯
}
return dp[d[0]][d[1]][d[2]][d[3]]=ans;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=0;i<n;i++)
for(int j=0;j<4;j++)
scanf("%d",&a[j][i]);
memset(d,0,sizeof(d));
memset(dp,-1,sizeof(dp));
memset(book,0,sizeof(book));
printf("%d\n",dfs(0));
}
}