UVA - 10559 Blocks 和 Vasya and Binary String CodeForces - 1107E (dp OR 记忆化搜索)

UVA - 10559 Blocks

题意:消消乐,每次连续相同的可以消除,分数加上长度的平方,问最多可以获得几分全部消完

题解:

区间dp + 记忆化搜索

dp[i][j][k] : (区间 [i,  j] 后面带上一段和 j 颜色相同的且长度为 k )的消消乐最大积分

1.消最后一段颜色和 j 颜色相同的

dp[i][j][k] <-- dp[i][j-1][0] + (k+1)^2

2.对于i <= l < j, 如果 l 和 j 的颜色相同, 那么可以把 [l+1, j-1]消掉, 那么剩下的一段就有 k+1 个和 l 相同的一段了

dp[i][j][k] <-- dp[i][l][k+1] + dp[l+1][j-1][0]

答案就是dp[1][n][0],采用记忆化搜索更方便转移

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<string.h>
using namespace std;
#define ll long long
#define mem(a, b) memset(a, b, sizeof(a))
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;

const int N = 205;
int dp[N][N][N];
int a[N];
int dfs(int l, int r, int k) {
    if(l > r) return 0;
    if(l == r) return (k+1)*(k+1);
    if(dp[l][r][k] > 0) return dp[l][r][k];
    dp[l][r][k] = dfs(l, r-1, 0) + (k+1)*(k+1);
    for (int i = l; i < r; i++) {
        if(a[i] == a[r]) {
            dp[l][r][k] = max(dp[l][r][k], dfs(l, i, k+1) +  dfs(i+1, r-1, 0));
        }
    }
    return dp[l][r][k];
}
int main() {
    int T, n;
    scanf("%d", &T);
    for(int cs = 1; cs <= T; cs++) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        mem(dp, -1);
        printf("Case %d: %d\n", cs, dfs(1, n, 0));
    }
    return 0;
}

Vasya and Binary String CodeForces - 1107E

题意:连续消除一定的相同的可以获得题目所给你的分数,问消除完所有的字符串之后可以获得的最大分数

题解:和上一题类似,可以使用上一题的转移方程,稍微改一下就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<string.h>
using namespace std;
#define ll long long
#define mem(a, b) memset(a, b, sizeof(a))
const int maxn = 1e2 + 10;
const int INF = 0x3f3f3f3f;

ll dp[maxn][maxn][maxn];
string s;
int a[maxn];

ll dfs(int l,int r,int k)
{
    if(l > r) return 0;
    if(l == r) return a[k + 1];
    if(dp[l][r][k] > 0) return dp[l][r][k];
    dp[l][r][k] = dfs(l,r - 1,0) + a[k + 1];
    for(int i = l; i < r; i++)
    {
        if(s[i] == s[r])
        {
            dp[l][r][k] = max(dp[l][r][k],dfs(l,i,k + 1) + dfs(i + 1,r - 1,0));
        }
    }
    return dp[l][r][k];
}
int main()
{
    int n;
    scanf("%d",&n);
    cin >> s;
    for(int i = 1; i <= n; i++)
        scanf("%d",&a[i]);
    memset(dp,-1,sizeof dp);
    //dfs(0,n - 1,0);
    cout << dfs(0,n - 1,0) <<endl;
}

原文地址:https://www.cnblogs.com/smallhester/p/11146790.html

时间: 2024-08-11 09:55:02

UVA - 10559 Blocks 和 Vasya and Binary String CodeForces - 1107E (dp OR 记忆化搜索)的相关文章

UVa Live 4794 - Sharing Chocolate 枚举子集substa = (s - 1) &amp; substa,记忆化搜索 难度: 2

题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2795 题意 x * y的巧克力,问能不能恰好切成n份(只能整数切),每块大小恰好ai 思路 明显,记忆化搜索. 这里参照刘书使用了sum来通过长计算宽 感想: 这种需要枚举子状态的题总是不敢枚举 代码 #include <algorithm> #includ

UVA 10891 Game of Sum(区间DP(记忆化搜索))

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1832 题目大意: 两个人在玩一个游戏: 给你一行n个数字,每次只能从左端或者右端取一个或多个数字. 每个人的分值就是他们各自取得的数字之和. 假设两人都足够聪明,问先手最多能比后手多多少分. 解题思路: 其实题目意思就是先手最多能得到多少分. 设dp[l][r]是取完[l,r]的

CF 1107 E. Vasya and Binary String

E. Vasya and Binary String 链接 分析: 对于长度为x的一段序列,我们可以dp出消除的过程的最优方案,背包即可. 然后区间dp,可以先合并完所有的点,即没相同的一段区间合并为一个点.设f[i][j][k]表示消完区间[i,j]和这段区间后面k个元素最大值,其中k个元素的颜色与点j的颜色相同. 转移:可以首先将j和后面k个元素消除,然后消除[i,j-1].也可以枚举一个和j颜色相同的点m,然后分别先消除[m+1,r-1],剩下的区间就和后面k个连在一起了,再递归求出. 代

UVA 10981 - String Morphing(记忆化搜索)

题目链接:10981 - String Morphing 题意:给定开始的字符串,要求根据表格变化成一个字符串,问变化的顺序(注意,不一定要最少步数) 思路:记忆化搜索,用map来存字符串的状态,一开始按最少步数去做TLE,其实只要找到一个符合的就可以了 代码: #include <stdio.h> #include <iostream> #include <string.h> #include <string> #include <map> u

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 - 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的计算用到位运算,还

状压DP+记忆化搜索 UVA 1252 Twenty Questions

题目传送门 1 /* 2 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 3 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 4 若和答案(自己拟定)相差小于等于1时,证说明已经能区分了,回溯.否则还要加问题再询问 5 */ 6 /************************************************ 7 * Author :Running_Time 8 * Created Time :