uva 10118,记忆化搜索

这个题debug了长达3个小时,acm我不能放弃,我又回来了的第一题!

一开始思路正确,写法不行,结果越改越乱

看了网上某神的代码,学习了一下

/*
 * Author:  Bingo
 * Created Time:  2015/3/2 21:23:20
 * File Name: uva10118.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
using namespace std;
const int maxint = -1u>>1;
int dp[45][45][45][45];
int a[4][45];
int f[5];
int n;
int ans;
int ok(int i,int j,int p,int q){
    int m[500];
    memset(m,0,sizeof(m));
    int top=0;
    for (int t=0;t<i;t++)
        m[top++]=a[0][t];
    for (int t=0;t<j;t++)
        m[top++]=a[1][t];
    for (int t=0;t<p;t++)
        m[top++]=a[2][t];
    for (int t=0;t<q;t++)
        m[top++]=a[3][t];
    sort(m,m+top);
    int cnt=0,tans=0;
    for (int t=0;t<top;){
        if (m[t]==m[t+1]){
            tans++;
            t+=2;
        }else {
            cnt++;
            t++;
        }
    }
    if (cnt<=5){
        ans=max(ans,tans);
        return 1;
    }
    return 0;
}
int dfs(int i,int j,int p,int q){
    if (i==n&&j==n&&p==n&&q==n) return 0;
    if (i<n){
        i++;
        if(ok(i,j,p,q)) {
            if (dp[i][j][p][q]){
                ans=max(ans,dp[i][j][p][q]);
                dp[i][j][p][q]=ans;
            }else {dp[i][j][p][q]=ans;dfs(i,j,p,q);}
        }
    }
    if (j<n){
        j++;
        if(ok(i,j,p,q)) {
            if (dp[i][j][p][q]){
                ans=max(ans,dp[i][j][p][q]);
                dp[i][j][p][q]=ans;
            }else {dp[i][j][p][q]=ans;dfs(i,j,p,q);}
        }
    }
    if (p<n){
        p++;
        if(ok(i,j,p,q)) {
            if (dp[i][j][p][q]){
                ans=max(ans,dp[i][j][p][q]);
                dp[i][j][p][q]=ans;
            }else {dp[i][j][p][q]=ans;dfs(i,j,p,q);}
        }
    }
    if (q<n){
        q++;
        if(ok(i,j,p,q)) {
            if (dp[i][j][p][q]){
                ans=max(ans,dp[i][j][p][q]);
                dp[i][j][p][q]=ans;
            }else {dp[i][j][p][q]=ans;dfs(i,j,p,q);}
        }
    }
}
int main () {
    while(cin>>n&&n){
        for (int i=0;i<n;i++) {
            cin >> a[0][i]>>a[1][i]>>a[2][i]>>a[3][i];
        }
        memset(dp,0,sizeof(dp));
        ans=0;
        memset(f,0,sizeof(f));
        //ok(3,3,3,3);
        dfs(0,0,0,0);
        cout << ans<<endl;
    }
    return 0;
}

时间: 2024-10-16 22:25:50

uva 10118,记忆化搜索的相关文章

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 10118 记忆化搜索

Little Bob is playing a game. He wants to win some candies in it - as many as possible. There are 4 piles, each pile contains N candies. Bob is given a basket which can hold at most 5 candies. Each time, he puts a candy at the top of one pile into th

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

题意:有4堆糖果,每堆有n(最多40)个,有一个篮子,最多装5个糖果,我们每次只能从某一堆糖果里拿出一个糖果,如果篮子里有两个相同的糖果, 那么就可以把这两个(一对)糖果放进自己的口袋里,问最多能拿走多少对糖果. 析:首先看到的是时间30s,这么长时间,一想应该是暴力了吧,后来一想应该是记忆化搜索,既然这么长时间,应该得优化一下,不然可能超时, 但是数据好像挺水,才运行了60ms,并不知道是怎么回事,接下来说说这个题,用 d[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 - 10118Free Candies(记忆化搜索)

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

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

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

UVa 10817 (状压DP + 记忆化搜索) Headmaster&#39;s Headache

题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老师教而且使得总工资最少. 分析: 因为s很小,所以可以用状态压缩. dp(i, s1, s2)表示考虑了前i个人,有一个人教的课程的集合为s1,至少有两个人教的集合为s2. 在递归的过程中,还有个参数s0,表示还没有人教的科目的集合. 其中m0, m1, s0, s1, s2的计算用到位运算,还

UVA - 10913Walking on a Grid(记忆化搜索)

题目:Walking on a Grid 题目大意:给出N * N的矩阵,每个格子里都有一个值,现在要求从(1,1)走到(n, n),只能往下,左,右这三个方向走,并且要求最多只能取k个负数,求这样的要求下能得到的走过格子的值之和最大. 解题思路:记忆化搜索,但是这里要四维的,因为要记录方向,为了防止走回头的路,并且取了几个负数也要记录.然后就是dfs了.状态转移方程:dp[x][y][d][k] = dp[x + dir[i][0]][y + dir[i][1]][i][k1] + G[x][