Codeforces 1183H DP 计算子序列数目

题意及思路:https://blog.csdn.net/mmk27_word/article/details/93999633

第一次见这种DP,有点像退背包的思想,如果发现有可能因为字母相同和前面算重时,把这种情况减去。

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 110;
int pre[30];
LL dp[maxn][maxn];
char s[maxn];
int main() {
	int n;
	LL k, cost = 0;
	scanf("%d%lld", &n, &k);
	scanf("%s",s + 1);
	dp[0][0] = 1;
	memset(pre, -1, sizeof(pre));
	for (int i = 1; i <= n; i++) {
		int now = s[i] - ‘a‘;
		int tmp = i - pre[now];
		dp[i][0] = 1;
		for (int j = 1; j <= i; j++) {
			dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
			if(pre[now] != -1 && j >= tmp) dp[i][j] -= dp[pre[now] - 1][j - tmp];
			dp[i][j] = min(dp[i][j], k);
		}
		pre[now] = i;
	}
	for (int i = 0; i <= n; i++) {
		LL tmp = min(dp[n][i], k);
		cost += tmp * i;
		k -= tmp;
		if(k == 0) break;
	}
	if(k > 0) printf("-1\n");
	else printf("%lld\n", cost);
}

  

原文地址:https://www.cnblogs.com/pkgunboat/p/11105299.html

时间: 2024-10-10 00:39:06

Codeforces 1183H DP 计算子序列数目的相关文章

CodeForces - 655E dp+贪心

题目链接:cf崩了,so. 参考博客:https://blog.csdn.net/kyleyoung_ymj/article/details/51628238 补题. 题意: 每个样例输入两行,第一行输入两个数字n,k,第二行输入一个字符串,你可以在第二行输入的字符串后面增加n个字符(k代表字符范围,比如k=2,那么你选择的字符有a,b:如果k=4,那么你可以选择的字符有a,b,c,d,就是从字符a开始的k个字符是可选择的).你要使输入字符串在后面增加n个指定范围的字符之后得到的字符串的子序列数

动态规划:计算路径数目(有限拐点)

一道有趣的动态规划题目 问题描述 给定一个 m x n 大小的矩阵,计算从左上角到右下角的路径数量(只允许向下或者向右移动),要求路径所经历的拐点数目不大于 k. 什么是拐点?如果我们本来沿着行移动,但是现在沿着列移动,则认为路径经过了一个拐点:或者本来沿着列移动,现在沿着行移动.拐点可能发生时有两种可能的情况: 在点 (i, j): 向右转: (i-1, j) -> (i, j) -> (i, j + 1) 向下转: (i, j-1) -> (i, j) -> (i + 1, j

codeforces 449D DP+容斥

Jzzhu and Numbers Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-20) Description Jzzhu have n non-negative integers a1, a2, ..., an. We will call a sequence o

计算子序列和是定值的子序列个数

题目如下: Counting Subsequences Time Limit: 5000 MSMemory Limit: 65536 K Description "47 is the quintessential random number," states the 47 society. And there might be a grain of truth in that. For example, the first ten digits of the Euler's const

codeforces的dp专题

1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个序列求和的最大值是多少 分析:设dp[i][j]在[j,n]范围内取了i个子序列求和所得的最大值,用sum[i]表示[1,i]的求和.转移方程为dp[i][j]=max(dp[i-1][j+m]+sum[j+m-1]-sum[j-1],dp[i][j+1]),表示要不要选择[j,j+m-1]这段为其

CodeForces 706C dp

C - Hard problem Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 706C Description Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve himself, so he as

DP之子序列问题

最近算法课又学习了一遍动态规划,看了一些求子序列的问题,特意集中mark一下以作备忘.. 最长上升子序列  问题描述 对于给定的整数数组序列,若它的一个子序列的元素是升序排列的,则称这个子序列是一个上升子序列.问题要求对于一给定整数数组,要求找到一个它的最长上升子序列. 算法实现 设A为给定的数组,A[i] 表示数组A的第i个元素,DP[i]表示表示以A[i]为结尾的最长上升子序列的长度,初始化DP[i]=0(i=1,2.....len(A)),则有状态转移方程:DP[i]=max{1,DP[j

dp计算后dfs回溯

http://codeforces.com/contest/4/problem/D 题意  给你n组高为h 宽为w的数  让你求他们最大的排列 每一个都要大于前面所有的h 和 w   并且大于题中给定你的 mih 和 miw #include <iostream> #include<algorithm> #include<math.h> #include<string.h> #include<stack> using namespace std;

暴力+分治+贪心+DP:最大子序列和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6 暴力:暴力列举所有可能的连续子数组,算法复杂度O(N^3)算法1: 1 int MaxSubseqSum1(int A[], int N) 2 { 3 int ThisSum, MaxSum = 0; 4 int i,j,k; 5 6 for (i = 0;