又从金矿模型开始了动态规划,感觉理解又深了一点吧,因为今天刷题不是很顺利,普通01背包很好应付,可是今天见的总是TLE,真是崩溃,同时也花费了大量时间在这上面,关于金矿模型的原文详见:http://blog.youkuaiyun.com/power721/article/details/4908401,里面也有参考代码。
关于总结别人写的很详细了,就通过个人学习所得说一下我学习的时候感觉迷茫的地方。我在学DP的时候有一种感觉就是别人讲的看懂了,但是自己动手写程序时却感觉无从下手,但是经过仔细分析之后慢慢就感觉有点思路了,就拿这个最简单的01背包类型的金矿模型题目来说吧,首先我最先想到的方法是递归,这个写起来就比较简单了,类似求n阶乘的做法,第二就是一般方法,别人在讲解的时候都说从最后一个子结构开始向前推,可是具体应用到程序里面该怎样写呢?这是我在学习的时候也曾遇到的,那我的做法就是:先把别人的程序走一遍,慢慢理解。下面解决我上面的提问:我们可以用一个表示人数为i的s[i]数组来表示当前能得到的最大金币数,可以想象最后的s[maxpeople]就是所要求的答案,具体过程可以观察程序,我觉得这个没什么说了,还是神马都自己走一遍,下面附上关于金矿模型我理解的程序,有兴趣的可以拷到自己编译器里调试一下,看看其中的过程,以帮助理解:最后总结一句:几乎所有的01背包类型的DP转移方程都是上面所提到的转移方程。
#include<cstdio>
using namespace std;
int max(int a,int b)
{
if(a>b)
return a;
return b;
}
int main()
{
int c[10002],w[10002];
int n,v,i,j;
while(scanf("%d%d",&v,&n)&&(v||n))
{
int s[10002]={0};
for(i=1;i<=n;i++)
scanf("%d%d",&c[i],&w[i]);
for(i=1;i<=n;i++)
for(j=v;j>=c[i];j--)
s[j]=max(s[j],s[j-c[i]]+w[i]);
printf("%d\n",s[v]);
}
return 0;
由于我理解的还不够深入,所以今天刷题时也遇到了种种困难,总是TLE,很是郁闷,明日计划:DP经典题型---单调子序列