版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/84569961
题目
https://www.luogu.org/problemnew/show/P2736
题解
1.这是一道二维费用的背包。(看到这种题,一旦知道了他要用背包来写,用哪种背包来写,基本就解决了。)
2.唯一不同的是:此题的状态转移方程比较不同。
//j代表光碟的数量,k代表这张光碟还有多长时间来录制歌曲
f[j][k] = max ( f[j][k] , //原封不动
max ( f[j-1][t] + 1 , //多增加一张光碟
f[j][k-a[i]] + 1) );//不增加光碟
应该是能明白的。
若是不明白,就把他带到代码里看看,手动模拟一下,应该就可以了。
代码
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int f=1,num=0;
char ch=getchar();
while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0', ch=getchar();
return num*f;
}
int f[21][21],a[21];
int main()
{
int n = read() , t = read() , m = read();
for (int i = 1;i <= n; ++i)
a[i]=read();
for (int i = 1;i <= n; ++i)//因为需要按照顺序,所以需要逐个找
for (int j = m;j >= 1; --j)//这个是01背包,每首歌只能录一次,
//不可以自己叠加自己的,所以只能从后往前
for (int k = t;k >= a[i]; --k)//和前面一样的道理,这一句和上一句换一下应该也
//没有问题,只是这样好解释一点
f[j][k] = max ( f[j][k] , max ( f[j-1][t] + 1 , f[j][k-a[i]] + 1) );
//原封不动 多增加一张光碟 不增加光碟
printf("%d\n" , f[m][t]);//第m个光碟t内存最多能存多少首歌
return 0;
}
神要是公然去跟人作对,那是任何人都难以对付的。——《荷马史诗》