今天写了几道dp练习题
都是四部曲,有些根据全局变量的特性可以省略
数字三角形
问题描述:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
给定一个数字三角形,如上,在这个三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。求出这个最大和。
输入格式:第一行给定一个n,随后是一个三角形
数据范围:题目保证所给数据不超过100
典型动态规划(求最值问题)
插一句求最值问题与贪心算法的区别
贪心:一开始就只往极端走,永不后悔 不回头也不会规划,只会选当前最好的,结果不一定最优
比如:用尽量少数量的钱币找钱
动归:保证子问题最优推得全局最优(一定)
回到这题
出口只有n条
子问题:每一层每一格步数都是可能路径最大的
如果从上往下,不能知道其他路径的数值大小
所以由下至上
初始条件&边界条件:不能走的路为0(全局变量默认了)
状态转移方程:将下一层最优保存在上一层累加
num[i][j]=max(num[i+1][j],num[i+1][j+1])+num[i][j];
#include<iostream>
#include<algorithm>
using namespace std;
int num[120][120];
int main(){
int i,j,k;
int n;
cin>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=i;j++)
{
cin>>num[i][j];
}
}
for(i=n-1;i>=1;i--)
{
for(j=1;j<=i;j++)
{
num[i][j]=max(num[i+1][j],num[i+1][j+1])+num[i][j];
}
}
cout<<num[1][1]<<endl;
return 0;
}
01串变换
对一个"01"串进行一次u变换被定义为:将其中的“0"变成“10","1"变成“01",初始串为"1",
求经过n(n< 1000)次变换后的串中有多少对00”。
下图表示经变换时串的情况。
此处产生00,必定要是10 和 01 即是上层的0 和 1 即在上层一个 1产生
所以我们构建两个数组保存每一层10 和 01累加变换出00的数量(当然开一个也行)
int num[1010][5];
//num[i][0] 10经过i次变换后00数量
//num[i][1] 01经过i次变换后00数量
(多写几个)观察知道 如果是10 那么下面不会出现00的情况
所以本层10变换出的00数量为
上一层10变幻出的00数量加上 上一层01变幻出的00数量
本轮01变换出00数量为10变幻出00数量加上(i%2) 这个当时怎么也找不到规律……
状态转移方程:
num[i][0] = num[i - 1][0] + num[i - 1][1];
num[i][1] = num[i][0] + (i % 2);//找规律着实麻烦
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int num[120][120];
int main()
{
int n;
cin >> n;
int i,j,k;
num[0][0] = num[0][1] = 0;//初始条件
for ( i = 1; i <= n; i++)
{
//cout<<" 123 "<<endl;
num[i][0] = num[i - 1][0] + num[i - 1][1];
num[i][1] = num[i][0] + (i % 2);
}
cout << num[n - 1][1];
return 0;
}