您的位置:首页 > 其它

记忆化搜索dp(UVa - 10118 Free Candies)

2015-03-21 15:06 134 查看
题意:有4堆糖果,每堆有n个,有一个篮子,最多装5个糖果,我们每次拿某一堆糖果最上面的一个,如果篮子里有两个相同的糖果,那么就可以把这一对糖果放进自己的口袋里,问最多能拿走多少对糖果。

思路:dp[a][b][c][d]表示对应堆的糖果拿走a,b,c,d个后,口袋里最多有多少糖果,对于篮子装满的情况dp值为0,记忆话搜索。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=41;

int dp[maxn][maxn][maxn][maxn];
int candy[4][maxn];
int top[4];
int H;
int basket[25];

int DP(int cnt)
{
    int a=top[0],b=top[1],c=top[2],d=top[3];
    if(cnt>=5)return dp[a][b][c][d]=0;
    if(dp[a][b][c][d]!=-1)return dp[a][b][c][d];
    int &ans=dp[a][b][c][d];
    ans=0;
    for(int i=0;i<4;i++)
    {
        if(top[i]<H)
        {
            int &tmp=basket[candy[i][top[i]]];
            top[i]++;
            if(tmp)
            {
                tmp=0;
                ans=max(ans,DP(cnt-1)+1);
                tmp=1;
            }
            else
            {
                tmp=1;
                ans=max(DP(cnt+1),ans);
                tmp=0;
            }
            top[i]--;
        }
    }
    return ans;
}
int main()
{
    while(scanf("%d",&H)!=EOF,H)
    {
        for(int j=0;j<H;j++)
            for(int i=0;i<4;i++)scanf("%d",&candy[i][j]);
        memset(dp,-1,sizeof(dp));
        memset(top,0,sizeof(top));
        memset(basket,0,sizeof(basket));
        printf("%d\n",DP(0));
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: