UVA - 10118 Free Candies 记忆化搜索

题目链接:UVA - 10118

题目是PDF就不贴了,大意就是有四堆糖果,每堆有n个,有个人有个能盛五个糖的篮子,每次可以任选一堆糖,取最上面的那个放到篮子里,如果篮子里有两个颜色相同的,就可以把这两个放到口袋里,篮子满了并且没有相同糖果的时候游戏结束,求他最多能拿到的糖果数。这道题的状态是每堆分别拿num个时,口袋里最多能有多少个糖,dp[num1][num2][num3][num4],也就是第一堆拿num1个,第二堆拿num2个.....时口袋里的糖数,每次循环尝试拿第i堆糖果的第num个,递归求解,初始状态为0,0,0,0. 这道题时限3s,我跑了差不多2s  = = ,看了一下别人的都是用数组记录某种糖是否在篮子里出现过,我是用的set,每次都需要插入删除,大概时间是差在这里了、

#include <cstdio>
#include <iostream>
#include <set>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 45;
int c[4][maxn],n,dp[maxn][maxn][maxn][maxn],num[4];
set<int > s;
int solve(set<int > s){
    if(dp[num[0]][num[1]][num[2]][num[3]]!=-1) return dp[num[0]][num[1]][num[2]][num[3]];
    if(s.size()==5) return dp[num[0]][num[1]][num[2]][num[3]]=0;
    int ans=0;
    for(int i=0;i<4;i++){
        if(num[i]==n) continue;
        num[i]++;
        if(s.count(c[i][num[i]])){
            s.erase(c[i][num[i]]);
            ans=max(ans,solve(s)+1);
            s.insert(c[i][num[i]]);
        }
        else {
            s.insert(c[i][num[i]]);
            ans=max(ans,solve(s));
            s.erase(c[i][num[i]]);
        }
        num[i]--;
    }
    return dp[num[0]][num[1]][num[2]][num[3]]=ans;
}
int main() {
    while(~scanf("%d",&n)&&n){
        memset(dp,-1,sizeof(dp));
        memset(num,0,sizeof(num));
        s.clear();
        for(int i=1;i<=n;i++)
            for(int j=0;j<4;j++)
                scanf("%d",&c[j][i]);
        printf("%d\n",solve(s));
    }
    return 0;
}

吐个槽,DP对我来说感觉真的是,比其他的东西要难学的多。。= = 希望能在题目中有所收获,就像教主说的 至少混个脸熟不是,哇哈哈哈。加油加油

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值