题目来源:王晓东,《算法设计与分析》
长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i<j<=n。试设计一个算法,计算出从游艇出租站1 到游艇出租站n所需的最少租金。
输入格式:
第1 行中有1 个正整数n(n<=200),表示有n个游艇出租站。接下来的第1到第n-1 行,第i行表示第i站到第i+1站,第i+2站, ... , 第n站的租金。
输出格式:
输出从游艇出租站1 到游艇出租站n所需的最少租金。
输入样例:
在这里给出一组输入。例如:
3
5 15
7
输出样例:
在这里给出相应的输出。例如:12
一般遇到这种题,就不要把思维局限在终点。要这样想:从任意一个数开始,如果前面一堆数<0,
那以他为底的尾串就是自己,否则是前面一堆数加上这个数得到递归方程m[j]=max(m[j-1]+num[j],num[j]),
或者if num[j]<0,m[j]=num[j],else m[j]=(m[j-1]+num[j])
代码省略 自己看书
(当然 直接分治法方法加备忘录 也是可以的)
4.都没有 自己挑 如0-1背包
0-1背包:给定种物品和一个容量为的背包,物品的重量是,其价值为,背包问题是如何使选择装入背包内的物品,使得装入背包中的物品的总价值最大。其中,每种物品只有全部装入背包或不装入背包两种选择。
这种题目二维数组的代表意义会十分的奇怪,比如说在0-1背包中,一个数代表从几号物品开始装,另一个数代表容量。
把二维数组顺序搞明白后,就会明显发现m[i][j]=max(m[i+1][j-i的价值],m[i+1][j])【前提:能装的下(j>i的价值),装不下直接m[i+1][j]】
然后把最后一行填好,就能往上填表了
#include<iostream>
using namespace std;
int main()
{
int n,capity,i,j;
cin>>n>>capity;
int item[100],percapity[100];
for(i=0;i<n;i++)
{
cin>>item[i];
cin>>percapity[i];
}
int bag[100][100];
for(j=0;j<=capity;j++)
{
if(j<percapity[n-1])
{
bag[n-1][j]=0;
}
else bag[n-1][j]=percapity[n-1];
}
for(i=n-2;i>=0;i--)
{
for(j=1;j<=capity;j++)
{
if(j>=percapity[i])
{
bag[i][j]=max(bag[i+1][j],bag[i+1][j-percapity[i]]+item[i]);
}
else bag[i][j]=bag[i+1][j];
}
}
cout<<bag[0][capity];
}
一般情况下,我们可以根据表之前的结果得到m[i][j]的结果,通常需要比较i,j和递归式里面i,j的关系,从而得到i和j在填表for循环里面的顺序,从而求i和j究竟递增,还是递增。一般递归式里面i比原i大递减,否则递增,j同理。