UVA - 10118 B - Free Candies

题意:有四堆糖果,每堆糖果有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));
    }
}

猜你喜欢

转载自blog.csdn.net/Vace___yun/article/details/81273798