做题前先回想好动态规划五部曲:
- 确定dp数组以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
1.摆动序列
题目链接:13.摆动序列 - 蓝桥云课 (lanqiao.cn)
#include<bits/stdc++.h>
using namespace std;
const int p=10000;
int m,n;
int dp[1010][1010]; //长度i以j结尾的摆动序列个数
int main()
{
cin>>m>>n;
for(int i=1; i<=n; i++)
{
dp[1][i]=1;
}
for(int i=1; i<=m; i++)
{
if(i&1) //奇数
{
for(int j=2; j<=n; j++)
{
dp[i][j]=(dp[i-1][j-1]+dp[i][j-1])%p; // 递推:选择当前数dp[i][j-1] 否则dp[i-1][j-1]
}
}
else
{
for(int j=n; j>=1; j--)
{
dp[i][j]=(dp[i-1][j+1]+dp[i][j+1])%p;
}
}
}
int sum=0;
for(int i=1; i<=n; i++)
{
sum=(sum+dp[m][i])%p;
}
cout<<sum<<endl;
return 0;
}
2.本质上升序列
#include <bits/stdc++.h>
using namespace std ;
int main()
{
int dp[1010]; // 不同递增子序列个数
memset(dp,0,sizeof(dp));
string s="tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl";
int n=s.size();
for(int i=0; i<n; i++)
{
dp[i]=1;
}
for(int i=0; i<n; i++)
{
for(int j=0;j<i;j++)
{
if(s[i]>s[j]) //所以遍历只能从0开始
{
dp[i]+=dp[j]; //以长度i结尾的不同递增子序列个数
}
if(s[i]==s[j])
{
dp[j]=0;
}
}
}
int sum=0;
for(int i=0;i<n;i++)
{
sum+=dp[i];
}
cout<<sum<<endl;
return 0 ;
}