dp

本文介绍了一种动态规划(DP)解题技巧,通过分析Concerts问题,详细阐述了如何通过列出所有可能情况并寻找规律来编写转移方程。文章提供了完整的代码实现,帮助读者理解DP在解决特定类型问题时的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我一般是不做dp题目的,但是这一个dp我必须要纪念一下,这是我做的为数不多的dp

因为我从这个dp里面学到了一个新技能----------列出所有情况,找规律写转移方程
之前我都是硬看,但是看不出来<哭>

以下内容学自这个博客

问题 A: Concerts
时间限制: 1 Sec  内存限制: 128 MB
提交: 314  解决: 74
[提交] [状态] [命题人:admin]
题目描述
John enjoys listening to several bands, which we shall denote using A through Z. He wants to attend several concerts, so he sets out to learn their schedule for the upcoming season. 
He finds that in each of the following n days (1 ≤ n ≤ 105), there is exactly one concert. He decides to show up at exactly k concerts (1 ≤ k ≤ 300), in a given order, and he may decide to attend more than one concert of the same band.
However, some bands give more expensive concerts than others, so, after attending a concert given by band b, where b spans the letters A to Z, John decides to stay at home for at least hb days before attending any other concert.
Help John figure out how many ways are there in which he can schedule his attendance, in the desired order. Since this number can be very large, the result will be given modulo 109 + 7.

输入
The first line contains k and n. The second line contains the 26 hb values, separated by spaces.
The third line contains the sequence of k bands whose concerts John wants to attend e.g.,AFJAZ, meaning A, then F etc. The fourth line contains the schedule for the following n days,specified in an identical manner.

输出
The number of ways in which he can schedule his attendance (mod 109 + 7).

样例输入
复制样例数据
2 10
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
AB
ABBBBABBBB
样例输出
10

题目大意:字符串只由AZ组成,给定s字符串长度k(k<=300),p字符串长度是n(<=1e5),再给定字母AZ匹配成功后需要间隔的次数a[27],再给出字符串s, p。求s匹配p的方案数

dp[i][j]:匹配到i位置时已经匹配了j个的方案数。
(1) s[j]==p[i]:dp[i][j] = dp[i-1][j] + dp[i-a[id]-1][j-1];
(2) s[j]!=p[i]:dp[i][j] = dp[i-1][j];

在这里插入图片描述

#include <iostream>
#include <cstdio>
using namespace std;
const int mod = 1e9 + 7 ;
int dp[100010][310] ;
int a[27];
char s[100010] , p[100010] ;
int main()
{
	int k , n ;
	scanf("%d%d",&k,&n) ;
	for(int i = 1;i <= 26 ;i ++)
	 scanf("%d",&a[i]) ;
	scanf("%s",s + 1) ;
	scanf("%s",p + 1) ;
	for(int i = 1;i <= n;i ++)
	 {
	 	dp[i][1] = dp[i - 1][1] ;
	 	if(s[1] == p[i]) dp[i][1] ++ ;
	 }
	 for(int i = 1;i <= n;i ++)
	  for(int j = 2;j <= k;j ++)
	   {
	   	dp[i][j] = dp[i - 1][j] ;
	   	if(s[j] == p[i]) 
	   	{
	   		 int id = s[j - 1] - 'A' + 1;
	   		 if(i - a[id] - 1 < 1) continue ;
	   		 dp[i][j] = (dp[i][j] + dp[i - a[id] - 1][j - 1]) % mod ;
	   	
		}
	   	
	   }
	   cout << dp[n][k] << endl ;
	   return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值