dp

我一般是不做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 ;
}

每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
原文地址:https://www.cnblogs.com/spnooyseed/p/12870926.html