精卫填海

题目描述

本题为改编题。

发鸠之山,其上多柘木。有鸟焉,其状如乌,文首,白喙,赤足,名曰精卫,其名自詨。是炎帝之少女,名曰女娃。女娃游于东海,溺而不返,故为精卫。常衔西山之木石,以堙于东海。——《山海经》

精卫终于快把东海填平了!只剩下了最后的一小片区域了。同时,西山上的木石也已经不多了。精卫能把东海填平吗?

事实上,东海未填平的区域还需要至少体积为 $v$ 的木石才可以填平,而西山上的木石还剩下 $n$ 块,每块的体积和把它衔到东海需要的体力分别为 $k$ 和 $m$。精卫已经填海填了这么长时间了,她也很累了,她还剩下的体力为 $c$。

输入格式

输入文件的第一行是三个整数:$v,n,c$。

从第二行到第 $n+1$ 行分别为每块木石的体积和把它衔到东海需要的体力。

输出格式

输出文件只有一行,如果精卫能把东海填平,则输出她把东海填平后剩下的最大的体力,否则输出 Impossible(不带引号)。

样例 #1

样例输入 #1

1
2
3
100 2 10
50 5
50 5

样例输出 #1

1
0

样例 #2

样例输入 #2

1
2
3
10 2 1
50 5
10 2

样例输出 #2

1
Impossible

提示

数据范围及约定

  • 对于 $20\%$ 的数据,$0<n \le 50$;
  • 对于 $50\%$ 的数据,$0<n \le 1000$;
  • 对于 $100\%$ 的数据,$0<n \le 10^4$,所有读入的数均属于 $[0,10^4]$,最后答案不大于 $c$。

题解

题目解析

这道题是求最达到 $v$ 的最小的体力, 我们退而求其次, 不以 $v$ 为背包容量, 而是以 $c$ 为背包容量, 看看达到 $c’$ 最多可以多少个石头. 然后我用的二分来找到最小的 $c’$ 接着输出 $c-c’$ 答案就出来了.

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/stdc++.h>
using namespace std;

#define endl "\n"
#define CIN_ ios::sync_with_stdio(0)
#define CIN cin.tie(0)
#define MAXN(size) const long long MAXN = size + 100
#define MOD(size) const long long MOD = size
#define mem(name,value) memset(name,value,sizeof(name))
#define fa(i,a,n) for(int i=a;i<=n;++i)
#define fb(i,a,n) for(int i=a;i>=n;--i)
#define T_ int T;cin >> T;while(T--)
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;

MAXN(1e4);
int dp[MAXN],a[2][MAXN];

signed main(){
CIN_;CIN;
int v,n,c;
cin >> v >> n >> c;
fa(i,1,n) cin >> a[0][i] >> a[1][i];
fa(i,1,n){
fb(j,c,a[1][i]){
dp[j] = max(dp[j],dp[j-a[1][i]]+a[0][i]);
}
}
if(dp[c] < v){
cout << "Impossible" << endl;
}else{
int l=0,r=c;
while(l < r){
int mid = l + r >> 1;
if(dp[mid] >= v) r = mid;
else l = mid + 1;
}
cout << c - r << endl;
}
return 0;
}