精卫填海
题目描述
本题为改编题。
发鸠之山,其上多柘木。有鸟焉,其状如乌,文首,白喙,赤足,名曰精卫,其名自詨。是炎帝之少女,名曰女娃。女娃游于东海,溺而不返,故为精卫。常衔西山之木石,以堙于东海。——《山海经》
精卫终于快把东海填平了!只剩下了最后的一小片区域了。同时,西山上的木石也已经不多了。精卫能把东海填平吗?
事实上,东海未填平的区域还需要至少体积为 v v v 的木石才可以填平,而西山上的木石还剩下 n n n 块,每块的体积和把它衔到东海需要的体力分别为 k k k 和 m m m。精卫已经填海填了这么长时间了,她也很累了,她还剩下的体力为 c c c。
输入格式
输入文件的第一行是三个整数: v , n , c v,n,c v,n,c。
从第二行到第 n + 1 n+1 n+1 行分别为每块木石的体积和把它衔到东海需要的体力。
输出格式
输出文件只有一行,如果精卫能把东海填平,则输出她把东海填平后剩下的最大的体力,否则输出 Impossible
(不带引号)。
样例 #1
样例输入 #1
100 2 10
50 5
50 5
样例输出 #1
0
样例 #2
样例输入 #2
10 2 1
50 5
10 2
样例输出 #2
Impossible
提示
数据范围及约定
- 对于 20 % 20\% 20% 的数据, 0 < n ≤ 50 0<n \le 50 0<n≤50;
- 对于 50 % 50\% 50% 的数据, 0 < n ≤ 1000 0<n \le 1000 0<n≤1000;
- 对于 100 % 100\% 100% 的数据, 0 < n ≤ 1 0 4 0<n \le 10^4 0<n≤104,所有读入的数均属于 [ 0 , 1 0 4 ] [0,10^4] [0,104],最后答案不大于 c c c。
思路
状态转移方程:
dp[j] = max(dp[j], dp[j - m[i]] + k[i]);
dp[j] 表示当前体力值为 j 时,精卫所能携带的最大石头体积。对于每一块石头 i,从 c 到 m[i] 枚举体力值 j,并尝试将它放入背包中。如果将石头 i 放入背包中所能得到的总体积 dp[j-m[i]] 加上 k[i] 大于 dp[j],则更新 dp[j] 的值。最后,从 0 到 c 遍历 dp 数组,找到第一个 dp[j] 大于等于 v 的位置,输出 c-j 即为所需体力值。如果遍历结束后仍然没有找到符合条件的位置,则输出 Impossible。
AC代码
#include <iostream>
#include <algorithm>
#define AUTHOR "HEX9CF"
using namespace std;const int N = 1e4 + 5;// 需要体积,总石头数,总体力
int v, n, c;
// 运送i块石头,j体力所能运送的最大体积
int dp[N];
// 每块体积,所需体力
int k[N], m[N];int main()
{cin >> v >> n >> c;for (int i = 1; i <= n; i++){cin >> k[i] >> m[i];}for (int i = 1; i <= n; i++){for (int j = c; j >= m[i]; j--){dp[j] = max(dp[j], dp[j - m[i]] + k[i]);}}for (int j = 0; j <= c; j++){if (dp[j] >= v){// 输出她把东海填平后剩下的最大的体力cout << c - j << endl;return 0;}}// cout << dp[n][c] << endl;cout << "Impossible" << endl;return 0;
}