dp算法部分总结
个人感受:听了几次课做了几个题之后,觉得这个dp并不和之前的算法一样,是一种思想,要更加偏向于问题的分析,而代码只是表示问题解决的过程,虽然并没有做太多题,说实话,有时候根本想不出怎么进行状态转化,尽管看了题解也需要再花一些时间思考,并不容易理解透。先从简单入手,其实也是有最基本的模板类型的,比如最大上升子序列,最大公共子串等等,一些问题根本思想就是这个,只不过数据的处理要麻烦一些,比如有个题是数据的输出那个序号,还是没搞懂为什么那样做,总之,还是要继续体会,继续想,多动手写一写会比较好,有助于理解。
这类问题具体解决的时候还有个共性的东西,比如dp[i]表示前i个数据怎么样怎么样,然后再从这个具体展开 所谓的状态改变
具体的就举几个自己掌握的模板例子吧
1.最大上升子序列问题
分析:要找最大的,那就先找出以dp[i]作为结尾的上升序列,再取最大值即可
int main()
{
int n,sum;
for(int i=1;i<=n;i++)
dp[i]=1;
for(int j=2;j<i;j++)
if(a[j]<a[i])
dp[i]=max(dp[i],dp[j]+1);
cout<<dp[i]<<endl;
2.最大公共子序列
思想:dp[i][j] 表示A的前i个 和B的前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])
3.最大字段和
思想 :dp[i]表示前i个数据的字段和
#include<iostream>
using namespace std;
int main()
{
int dp[100];
int sum=-1;
int a[6]={5,6,-1,5,4,-7};
for(int i=0;i<=5;i++){
dp[i]=max(dp[i-1]+a[i],0);
if(dp[i]>sum) sum=dp[i];
}
cout<<sum<<endl;
return 0;
}
注意一个问题 字段是连续的 序列可以不连续!
最后一个例子
有关路径输出的,脑门疼,非得用写出来才略懂里的,真的很神奇的操作,这个代码不是自己写的,搜的题解,然后扣明白的!!要掌握这种方法
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
int w;
int s;
int no;
}mice[1005];
struct node2
{
int sum=1;
int pre=0;
}dp[1005];
bool cmp(node a, node b)
{
if (a.w == b.w)
return a.s > b.s;
return a.w < b.w;
}
int main()
{
int k = 0, max, t;
while (cin>>mice[k].w>>mice[k].s &&mice[k].w&&mice[k].s)
{
mice[k].no = k + 1;
k++;
}
sort(mice, mice + k, cmp);
max = 1;
t = 1;
for (int i = 1; i < k; i++)
{
for (int j = 0; j < i; j++)
{
if (mice[j].s > mice[i].s&&mice[j].w < mice[i].w)//找出质量大速度小的
{
if (dp[i].sum < dp[j].sum + 1)//最大连续序列
{
dp[i].sum = dp[j].sum + 1;
dp[i].pre = j;
}
}
}
if (dp[i].sum > max)
{
max = dp[i].sum;
t = i;
}
}
cout << max << endl;
int m[1005];
for (int i = 1; i <= max; i++)
{
m[i] = t;
t = dp[t].pre;
}
for (int j = max; j >= 1; j--)
cout<<mice[m[j]].no<<endl;
}
关键是路径输出 很难搞懂的地方(对我来说)
{
if (dp[i].sum < dp[j].sum + 1)//最大连续序列
{
dp[i].sum = dp[j].sum + 1;
dp[i].pre = j;//记录所使用数据的序号
}
}
}
if (dp[i].sum > max)
{
max = dp[i].sum;
t = i;//这个是最后一个的序号
}
}
cout << max << endl;
int m[1005];
for (int i = 1; i <= max; i++)
{
m[i] = t;
t = dp[t].pre;//具体为什么这么操作我也不明白,我试了试的确是这样。。。。。
}
for (int j = max; j >= 1; j--)
cout<<mice[m[j]].no<<endl;
}