UVa 10118 Free Candies (记忆化搜索+哈希)

题意:有4堆糖果,每堆有n(最多40)个,有一个篮子,最多装5个糖果,我们每次只能从某一堆糖果里拿出一个糖果,如果篮子里有两个相同的糖果,

那么就可以把这两个(一对)糖果放进自己的口袋里,问最多能拿走多少对糖果。

析:首先看到的是时间30s,这么长时间,一想应该是暴力了吧,后来一想应该是记忆化搜索,既然这么长时间,应该得优化一下,不然可能超时,

但是数据好像挺水,才运行了60ms,并不知道是怎么回事,接下来说说这个题,用 d[a,b,c,d] 来表示 分别从 第一,二,三,四堆拿的最多糖果,

如果篮子满了就返回,如果拿空了某一堆要停止再拿了,再就是如果曾经有过这个状态直接返回值就好,不用再重复计算,节约时间,再就是用Hash,

来匹配糖果,原来全是false,如果从true变成false,那么就说明有成对,就拿出来,如果从false变成true,说明又得住篮子里放一颗,一定要记住,

要及时改回来,刚开始忘了,怎么运行都不对。。。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int maxn = 40 + 5;
int d[maxn][maxn][maxn][maxn];
int n, a[4][maxn], top[4];//top表示第 i 堆糖果拿到第几个了
bool Hash[maxn];//判断是不是成对

int solve(int cur){
    if(d[top[0]][top[1]][top[2]][top[3]] != -1)  //如果已经存在这种状态,直接返回就好了
        return d[top[0]][top[1]][top[2]][top[3]];
    if(cur == 5)  return 0;//篮子满了

    int ans = 0;
    for(int i = 0; i < 4; ++i){
        if(top[i] == n)  continue;//某一堆空了

        int x = a[i][top[i]++];
        if(Hash[x]){//从true变成false
            Hash[x] = false;
            ans = max(ans, solve(cur-1)+1);
            Hash[x] = true;//要记得及时改回来
        }
        else{
            Hash[x] = true;
            ans = max(ans, solve(cur+1));
            Hash[x] = false;
        }
        --top[i];
    }
    return d[top[0]][top[1]][top[2]][top[3]] = ans;//返回并赋值给d
}

int main(){
//    freopen("in.txt", "r", stdin);
    while(scanf("%d", &n) == 1 && n){
        for(int i = 0; i < n; ++i)//把每一列糖果变成每一行
            for(int j = 0; j < 4; ++j)
                scanf("%d", &a[j][i]);

        memset(d, -1, sizeof(d));//清零
        memset(top, 0, sizeof(top));
        memset(Hash, false, sizeof(Hash));
        printf("%d\n", solve(0));
    }
    return 0;
}
时间: 2024-10-09 15:49:01

UVa 10118 Free Candies (记忆化搜索+哈希)的相关文章

UVA 707 - Robbery(记忆化搜索)

UVA 707 - Robbery 题目链接 题意:在一个w * h的图上,t个时刻,然后知道一些信息,每个时刻没有小偷的矩阵位置,问哪些时刻可以唯一确定小偷位置,和确定小偷是否已经逃走,如果没逃走,但是也没有时刻可以可以确定小偷位置,就是不知到 思路:记忆化搜索,dp[x][y][ti]表示在x,y位置,ti时刻时候,小偷是否可能出现在这个位置,1表示有可能,0表示没可能,由于小偷一次最多只能上下左右走一步或者不走,所以去dfs一遍即可 最后判断的时候,如果有一个时刻没有一个1,就表示已经逃走

UVa 1629 Cake slicing (记忆化搜索)

题意:一个矩形蛋糕上有好多个樱桃,现在要做的就是切割最少的距离,切出矩形形状的小蛋糕,让每个蛋糕上都有一个樱桃,问最少切割距离是多少. 析:很容易知道是记忆化搜索,我们用dp[u][d][l][r]来表示,上界是u,下界是d,左边是l,右边是r,然后不断切割,不过要注意切的时候是按缝隙切, 缝隙多一条,那么我们可以补上一条,用0来补齐,然后就进行计算就好. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #in

uva 10891 区间dp+记忆化搜索

https://vjudge.net/problem/UVA-10891 给定一个序列x,A和B依次取数,规则是每次只能从头或者尾部取走若干个数,A和B采取的策略使得自己取出的数尽量和最大,A是先手,求最后A-B的得分. 令 f(i,j)表示对于[i,j]对应的序列,先手可以从中获得的最大得分,那么答案可以写为  f(i,j)-(sum(i,j)-f(i,j)),也就是 2*f(i,j)-sum(i,j) 下面讨论f(i,j)的写法,显然递归的形式更好表达一些,为了防止重复的计算使用记忆化搜索.

UVa 10118 记忆化搜索 Free Candies

假设在当前状态我们第i堆糖果分别取了cnt[i]个,那么篮子里以及口袋里糖果的个数都是可以确定下来的. 所以就可以使用记忆化搜索. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 45; 7 const int maxm = 4; 8 9 int n; 10 11 int candy[maxn][maxm

UVA - 10118Free Candies(记忆化搜索)

题目:UVA - 10118Free Candies(记忆化搜索) 题目大意:给你四堆糖果,每个糖果都有颜色.每次你都只能拿任意一堆最上面的糖果,放到自己的篮子里.如果有两个糖果颜色相同的话,就可以将这对糖果放进自己的口袋.自己的篮子最多只能装5个糖果,如果满了,游戏就结束了.问你能够得到的最多的糖果对数. 解题思路:这题想了好久,好不容易把状态想对了,结果脑子发热,又偏离了方向.dp[a][b][c][d]:四堆糖果现在在最上面的是哪一个.因为下面的糖果如果确定了,那么接下了不管你怎么取,最优

uva 1076 - Password Suspects(AC自动机+记忆化搜索)

题目链接:uva 1076 - Password Suspects 题目大意:有一个长度为n的密码,存在m个子串,问说有多少种字符串满足,如果满足个数不大于42,按照字典序输出. 解题思路:根据子串构建AC自动机,然后记忆化搜索,dp[i][u][s]表示第i个字符,在u节点,匹配s个子串. #include <cstdio> #include <cstring> #include <queue> #include <string> #include <

UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)

题目链接:uva 1252 题意: 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1. 问最少提问次数,可以把所有字符串区分开来. 思路来源于:点击打开链接 思路: m很小,可以考虑状态压缩. dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数. 当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0: 不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为

uva 10581 - Partitioning for fun and profit(记忆化搜索+数论)

题目链接:uva 10581 - Partitioning for fun and profit 题目大意:给定m,n,k,将m分解成n份,然后按照每份的个数排定字典序,并且划分时要求ai?1≤ai,然后输出字典序排在k位的划分方法. 解题思路:因为有ai?1≤ai的条件,所以先记忆化搜索处理出组合情况dp[i][j][s]表示第i位为j,并且剩余的未划分数为s的总数为dp[i][j][s],然后就是枚举每一位上的值,判断序列的位置即可. #include <cstdio> #include

UVA - 10817 Headmaster&#39;s Headache (状压dp+记忆化搜索)

题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所能教的所有科目. 2.已聘老师必须选,候选老师可选可不选. 3.dfs(cur, subject1, subject2)---求出在当前已选cur个老师,有一个老师教的科目状态为 subject1,有两个及以上老师教的科目状态为 subject2的情况下,最少的雇佣费用. dp[cur][subje