机房练习题
- ps. 闲人…
免进… 看就看吧 - 言归正传,这道题是分组背包(我用的01…,后来…,好吧,其实本来用的就是分组,自己都不知道)。pps. 分组背包的题在 这里
- ppps. 刚教完小师弟,手指头都紫了(粉笔的颜色)
题干分析&思路详解
先推导大表,如下图: (最好自己从新画一遍)
- 这里能够看出,每一个数均可从上一个推导而来(注意,不是一定!!!)。例如,(3,3)可以从(2,3)推导而来。即:
f [ i ] [ j ] = f [ i − 1 ] [ j ] f[i][j]=f[i-1][j] f[i][j]=f[i−1][j]
pppps. 机房网太差,刚打完的博客,全没了~~~~(>_<)~~~~
- 与此同时,它也可以从另一个位置推导。即 :
f [ i ] [ j ] = f [ i − 1 ] [ j − k ] + a [ i ] [ k − n a m e ] f[i][j]=f[i-1][j-k]+a[i][k-name] f[i][j]=f[i−1][j−k]+a[i][k−name]
i为考前i个科目 1~n
j为总共花j 分钟 (注意:包括写名字花的时间) name~t
k为在第i个科目上花k分钟 (同样包括写名) 0(!!!)~j
name如题意为写名的时间
- 所以,得到状态转移方程如下:
f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i − 1 ] [ j − k ] + a [ i ] [ k − n a m e ] ) f[i][j]=max(f[i][j],f[i-1][j-k]+a[i][k-name]) f[i][j]=max(f[i][j],f[i−1][j−k]+a[i][k−name]) - 代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,t,name,k,ans,a[11][101],f[11][101];
int main(){
scanf("%d %d %d",&t,&n,&name);
for(int i=1;i<=n;i++)
for(int j=1;j<=t;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=name;j<=t;j++){
f[i][j]=f[i-1][j];// 初始化
for(int k=0;k<=j;k++)
if(k-name>=0) f[i][j]=max(f[i][j],f[i-1][j-k]+a[i][k-name]); //方程
}
cout<<f[n][t]<<endl;
return 0;
}