小标题的超链接为原题链接,点击跳转
这类dp主要是一些状态比较容易表示,转移方程比较好想,问题比较基本常见的。主要包括递推、LIS(最长递增序列),LCS(最长公共子序列)
题目
代码
// 数字三角形
#include
using namespace std;
const int N = 1e2 + 10;
int a[N][N]; // 存储结点的值
int b[N][N]; // 存储到达该结点的最大的路径和
int n;
int main()
{
cin >> n;
for(int i=1; i<=n; i++)
for(int j=1; j<=i; j++)
cin >> a[i][j];
b[1][1] = a[1][1];
for(int i=2; i<=n; i++)
for(int j=1; j<=i; j++)
{
if(j == 1)
{
b[i][j] = b[i-1][j] + a[i][j];
}
else if(j == i)
{
b[i][j] = b[i-1][j-1] + a[i][j];
}
else
{
b[i][j] = max(b[i-1][j], b[i-1][j-1]) + a[i][j];
}
}
int res = 0;
if(n%2 == 1)
res = b[n][n/2+1];
else
res = max(b[n][n/2], b[n][n/2+1]);
cout << res;
}
题目
代码
// 母牛的故事
#include
using namespace std;
const int N = 60;
int cow[N];
int n;
int main()
{
cow[1] = 1;
for(int i=2; i<=N; i++)
{
if(i >= 4) cow[i] = cow[i-3] + cow[i-1];
else cow[i] = cow[i-1] + 1;
}
int year;
do
{
cin >> year;
cout << cow[year] << endl;
}while(year);
}
题目
代码
// 一只小蜜蜂
#include
using namespace std;
typedef long long ll;
const int N = 55;
ll dp[N];
int main()
{
dp[0] = 0;
dp[1] = 1;
// 构造斐波那契
for(int i=2; i<=N; i++)
dp[i] = dp[i-1] + dp[i-2];
// 输入输出
int n, a, b;
cin >> n;
while(n--)
{
cin >> a >> b;
cout << dp[b-a+1] << endl;
}
return 0;
}
题目
代码
// LIS 最长上升子序列
// 对每一个位置i,利用j∈[1, i-1]进行遍历,找出由前面哪个状态获得的dp[i]最优,复杂度O(n*m)
// 状态转移方程:dp[i] = max(dp[i], dp[j]+1)
// 最后输出dp数组中的max_element
#include
using namespace std;
int dp[1010]={0};
int a[1010]={0};
int main()
{
int n;
cin >> n;
for(int i=1; i<=n; i++)
{
cin >> a[i];
dp[i] = 1;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=i-1; j++)
if(a[i] > a[j])
dp[i] = max(dp[i], dp[j]+1);
cout << *max_element(dp+1, dp+n+1);
}
#include
using namespace std;
int n;
int a[110];
int dp_up[110]={0};
int dp_down[110]={0};
int main(){
cin >> n;
for(int i=1; i<=n; i++){
cin >> a[i];
dp_up[i] = dp_down[i] = 1;
}
for(int i=1; i<=n; i++){
for(int j=1; j<=i-1; j++){
if(a[i] > a[j]) dp_up[i] = max(dp_up[i], dp_up[j]+1);
}
}
for(int i=n; i>=1; i--){
for(int j=n; j>=i+1; j--){
if(a[i] > a[j]) dp_down[i] = max(dp_down[i], dp_down[j]+1);
}
}
int ans=0;
for(int i=1; i<=n; i++) ans = max(ans, dp_down[i]+dp_up[i]-1);
cout << n-ans;
}
#include
using namespace std;
int n;
int a[110]={0};
int dp[110]={0};
int main(){
int k; cin>>k;
while(k--){
cin >> n;
int maxlen=0;
for(int i=1; i<=n; i++){
cin >> a[i];
dp[i] = 1;
}
//计算后向最大下降子序列
for(int i=1; i<=n; i++){
for(int j=1; j<=i-1; j++){
if(a[i]<a[j]) dp[i] = max(dp[i], dp[j]+1);
}
}
maxlen = *max_element(dp+1, dp+n+1);
//计算前向最大上升子序列
for(int i=1; i<=n; i++) dp[i] = 1;
for(int i=1; i<=n; i++){
for(int j=1; j<=i-1; j++){
if(a[i]>a[j]) dp[i] = max(dp[i], dp[j]+1);
}
}
maxlen = max(maxlen, *max_element(dp+1, dp+n+1));
// for(int i=1; i<=n; i++) cout << dp[i] << " ";
// cout << endl;
cout << maxlen << endl;
}
}
#include
using namespace std;
char a[1010], b[1010];
int dp[1010][1010] = {0};
int main(){
while(cin >> a+1 >> b+1){
int n = strlen(a+1), m = strlen(b+1);
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
if(a[i] == b[j]) dp[i][j] = dp[i-1][j-1]+1;
else dp[i][j] = max(dp[i][j-1], dp[i-1][j]);
}
}
cout << dp[n][m] << endl;
}
return 0;
}