租用游艇
原题链接
题意:n个游艇出租站,r(i, j)为游艇出租站i到游艇出租站j之间的租金,求出租站1到出租站n所需最少租金。
题解:我认为与“三角形”的dp类似
#include<bits/stdc++.h>
using namespace std;
const int N=210;
int a[N][N],f[N];//f[i]标记i-n的最短
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
cin>>a[i][j];
f[i]=0x3f;
}
}
for(int i=n-1;i>=1;i--)//从4-1
{
for(int j=i+1;j<=n;j++)//i+1-5
{
f[i]=min(f[i],a[i][j]+f[j]);
//f[i]为i-n, a[i][j]+f[j]为i-j+j-n;
//例如2-5,要与2-5、2-3-5、2-4-5相比较
}
}
cout<<f[1];
}
/*
5
5 15 18 22
4 7 13
8 5
3
f[i] : 14 9 5 3 0
自下而上,从n-1->n....1->n
*/
装箱问题
原题链接 NOIP 2001 普及组第四题
题意:n个体积为V的物品中,任取果敢个装入箱内,使箱子所剩体积最小。
题解:0-1背包简单变形
#include<bits/stdc++.h>
using namespace std;
const int N=2e4+10;
int f[N],wei[N];
/*
取max
一共有v空间,n件物品
装或者不装
f[j]表示装了j空间的已用空间
背包问题:容量 和价值--->容量和已用容量
*/
int main()
{
int v,n;
cin>>v>>n;
for(int i=1;i<=n;i++)
{
cin>>wei[i];
//use[i]=wei[i];
}
for(int i=1;i<=n;i++)
{
for(int j=v;j>=wei[i];j--)//如果是[v,0]会越界
{
f[j]=max(f[j],f[j-wei[i]]+wei[i]);
}
}
cout<<v-f[v];
return 0;
}
5倍经验日
原题链接
题意:能量大小为x,有n个好友,给定失败和胜利分别可以获得的经验值和打败每个好友所需的能量,求最多能获得的经验值。
题解:
变形的0-1背包,针对打败或者不打败都能获得经验。所以,可能可以打败(i>=use)时 dp[i] = max( di[i]+lose[i], dp[i-use[i]] +win[i];
; 或者需要的能力已经超过限制(i<use)时【因为所有人都要被打一次】dp[i]+=use[i];
参考题解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10;
ll f[N];
//int lose[N],use[N],win[i];
/*
打或者不打,不打本身有经验,打了消耗x但是有更多经验
f[j]表示体力花费j时的最大价值
*/
struct node{
ll lose,win,use;
}e[N];
int main()
{
int n,x;
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>e[i].lose>>e[i].win>>e[i].use;
}
for(int i=1;i<=n;i++)
{
for(int j=x;j>=0;j--)
{
if(j>=e[i].use) f[j]=max(f[j]+e[i].lose,f[j-e[i].use]+e[i].win);
else{
f[j]+=e[i].lose;
}
}
}
cout<<f[x]*5;
}
总结
道阻且长,继续加油!