一、信息学OJ:1271:【例9.15】潜水员
(1)问题描述
潜水员为了潜水要使用特殊的装备。他有一个带2种气体的气缸:一个为氧气,一个为氮气。让潜水员下潜的深度需要各种的数量的氧和氮。潜水员有一定数量的气缸。每个气缸都有重量和气体容量。潜水员为了完成他的工作需要特定数量的氧和氮。他完成工作所需气缸的总重的最低限度的是多少?
例如:潜水员有5个气缸。每行三个数字为:氧,氮的(升)量和气缸的重量:
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
如果潜水员需要5升的氧和60升的氮则总重最小为249(1,2或者4,5号气缸)。
你的任务就是计算潜水员为了完成他的工作需要的气缸的重量的最低值。
【输入】
第一行有2整数m,n(1≤m≤21,1≤n≤79)。它们表示氧,氮各自需要的量。
第二行为整数k(1≤n≤1000)表示气缸的个数。
此后的k行,每行包括ai,bi,ci(1≤ai≤21,1≤bi≤79,1≤ci≤800)3ai,bi,ci(1≤ai≤21,1≤bi≤79,1≤ci≤800)3整数。这些各自是:第i个气缸里的氧和氮的容量及汽缸重量。
【输出】
仅一行包含一个整数,为潜水员完成工作所需的气缸的重量总和的最低值。
【输入样例】
5 60
5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119
【输出样例】
249
(2)代码实现
#include <bits/stdc++.h>
#define ll long long
#define inf 1<<30
#define PII pair<int,int>
using namespace std;
int n,m,dp[25][85],k,x,y,z;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> k;
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;//初始化
while(k--)
{
cin >> x >> y >> z;
for(int i=n;i>=0;i--)
{
for(int j=m;j>=0;j--)
{
int t1=i+x,t2=j+y;
t1=min(t1,n);
t2=min(t2,m);
dp[t1][t2]=min(dp[t1][t2],dp[i][j]+z);
}
}
}
cout << dp[n][m] << endl;
return 0;
}
二、信息学OJ:1272:【例9.16】分组背包
(1)题目描述
一个旅行者有一个最多能装V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,WnW1,W2,...,Wn,它们的价值分别为C1,C2,...,CnC1,C2,...,Cn。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
【输入】
第一行:三个整数,V(背包容量,V≤200),N(物品数量,N≤30)和T(最大组号,T≤10);
第2..N+1行:每行三个整数Wi,Ci,PWi,Ci,P,表示每个物品的重量,价值,所属组号。
【输出】
仅一行,一个数,表示最大总价值。
【输入样例】
10 6 3
2 1 1
3 3 1
4 8 2
6 9 2
2 8 3
3 9 3
【输出样例】
20
(2)代码实现
#include<bits/stdc++.h>
#define M 1005
using namespace std;
int W,T,N,i,j,k;
int w[M],c[M],p,dp[M];
int group[M][M];
int main()
{
cin >> W >> N >>T;
memset(dp,0,sizeof(dp));
memset(group,0,sizeof(group));
for(i = 1; i <= N;i++)
{
cin >> w[i] >> c[i] >> p ;
group[p][++group[p][0]] = i;
}
for(i = 1 ; i <= T;i++)
{
for(j = W; j >= 0; j--)
{
for(k = 1; k <= group[i][0];k++)
{
int q = group[i][k];
if(j >= w[q])
dp[j] = max(dp[j],dp[j-w[q]]+c[q]);
}
}
}
printf("%d\n",dp[W]);
return 0;
}
三、信息学OJ:1273:【例9.17】货币系统
(1)问题描述
给你一个n种面值的货币系统,求组成面值为m的货币有多少种方案。
【输入】
第一行为n和m。
【输出】
一行,方案数。
【输入样例】
3 10
1
2
5
【输出样例】
10
(2)代码实现
#include<stdio.h>
int main()
{
long long n,m,dp[10005],a[10005],i,j;
while(scanf("%lld %lld",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
dp[0]=1;
for(i=1;i<=n;i++)
{
for(j=a[i];j<=m;j++)
dp[j]+=dp[j-a[i]];
}
printf("%lld\n",dp[m]);
}
}