【记忆化搜索】UVA 10118 free candy

题意:有四根管道,每根里面有n颗糖,每次只能从管道的最上面拿糖进篮子里。如果篮子里面有两颗颜色一样的糖(数值大小一样),那么Bob可以将这两颗糖揣进自己的口袋里,如果篮子里的糖数为5颗,就结束。问Bob最多能拿到几颗糖

思路:将每根管道拿出的糖数num[1],num[2],num[3],num[4]作为一种状态,求解该状态下还能拿多少颗糖

留了一个疑惑在返回和输出的地方_(:з」∠)_

#include<iostream>
#include<stdlib.h>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=50;
int in[25];          //颜色i是否在篮子里
int dp[N][N][N][N]; //四个管道分别选了前i,j,k,l个糖时还能取的腰包里最大糖数
int a[N][4];
int top[4];         //top[i]记录第i个管道在选第几颗糖
int n;
int dfs(int cnt)    //求每个状态下还能选的糖的最大值   cnt表示篮子里面有cnt颗糖
{
    int &ans=dp[top[0]][top[1]][top[2]][top[3]];
    if(ans!=-1) return ans;
    if(cnt==5) return ans=0;
    ans=0;
    for(int i=0;i<4;++i)
    {
        if(top[i]==n) continue;
        int color=a[top[i]++][i];
        if(in[color])
        {
            in[color]=0;            //已经有这个颜色了,那么我要把它拿出来
            ans=max(ans,dfs(cnt-1)+1);//因为拿出来了,所以篮子里糖数减少了1
            in[color]=1;            //回溯
        }
        else
        {
            in[color]=1;
            ans=max(ans,dfs(cnt+1));//放进去了一颗,篮子里糖数增加1
            in[color]=0;
        }
        top[i]--;
    }
    return dp[top[0]][top[1]][top[2]][top[3]]=ans;  //为啥我直接返回ans,输出答案的时候输出dp[0][0][0][0]就不对??

}
int main()
{

    while(cin>>n)
    {
        if(!n) break;
        memset(in,0,sizeof(in));
        memset(dp,-1,sizeof(dp));       //初始化为该状态未计算过
        memset(top,0,sizeof(top));
        for(int i=0;i<n;++i)
            for(int j=0;j<4;++j)
            {
                cin>>a[i][j];
            }
        cout<<dfs(0)<<endl;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值