4.1w+
社区成员
P1048 [NOIP2005 普及组] 采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
f[i, j] 表示从前 i 个草药里面采,花费时间不超过 j 的最大价值
优化成一维,从前往后遍历,确保每次上一层被计算
#include<iostream>
using namespace std;
const int N = 1010;
int f[N];
int n, m;
int main(){
cin>>m>>n;
for(int i = 1; i <= n; i++){
int v, w;
cin>>v>>w;
for(int j = m; j >= v; j--)
f[j] = max(f[j], f[j-v] + w);
}
cout<<f[m]<<endl;
return 0;
}
P1616 疯狂的采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
注意数据范围就行
#include<iostream>
using namespace std;
typedef long long LL;
const int N = 1e7 + 5;
LL f[N];
LL n, m;
int main(){
scanf("%lld%lld", &m, &n);
for(int i = 1; i <= n; i++){
LL v, w;
scanf("%lld%lld", &v, &w);
for(int j = v; j <= m; j++)
f[j] = max(f[j] , f[j-v] + w);
}
printf("%lld", f[m]);
return 0;
}
对于每组数据进行处理,这是一道数字三角形模型衍生题
使用闫式分析法即可,f数组表示到达(i, j ) 时能够摘到的最多花生数量
有两种可能,分别是从左边来的,从上面来的,每次取每步方案的最大值,再加上本身的数量
#include<iostream>
#include<cstring>
using namespace std;
const int N = 110;
int n;
int a[N][N], f[N][N];
int main(){
scanf("%d", &n);
while(n--){
int r, c;
scanf("%d%d", &r, &c);
memset(a, 0, sizeof a);
memset(f, 0, sizeof f);
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++)
scanf("%d", &a[i][j]);
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++)
f[i][j] = max(f[i][j-1], f[i-1][j]) + a[i][j];
printf("%d\n", f[r][c]);
}
return 0;
}
P1077 [NOIP2012 普及组] 摆花 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
注意k的取数,二维要从0开始,因为 f[i-1,j-k]
f[i,j]表示从前 i 个物品里面选,不超过 j 盆的合理方案数量
状态计算:
1、不取 f[i-1, j]
2、取 f[i-1, j-k] k的范围( 0 ~ min(a[i],j ) )
#include<iostream>
using namespace std;
const int N = 110, MOD = 1000007;;
int n, m;
int f[N], a[N];
int main(){
cin>>n>>m;
for(int i = 1; i <= n; i++) cin>>a[i];
f[0] = 1; //从0个里面选不超过0盆也是一种方案
for(int i = 1; i <= n; i++)
for(int j = m; j >= 0; j--)
for(int k = 1; k <= min(j, a[i]) ; k++) //k要从1开始因为f[j-k]不能多加一次
f[j] = (f[j] + f[j-k]) % MOD;
cout<<f[m]<<endl;
return 0;
}