zl程序教程

您现在的位置是:首页 >  其它

当前栏目

【洛谷】P1510 精卫填海

洛谷
2023-09-14 09:13:20 时间

1.题意

2.分析

裸的 0/1背包

3.代码

1.数组定义

  • dp[i] 表示到达体积i时需耗费的最小体力
  • need 表示东海填平需要的木石体积
  • v[i],cos[i] 每块石头的体积以及消耗的体力
  • n:西山的木石
  • rest:精卫剩余的体力

2.坑点:
题目说至少需要体积为v(代码里对应为need)的木石才可以填平。也就是说,我们可以在 >=need 的结果集中选择一个最小的体力消耗的就OK了。

#include<iostream>
#include<algorithm>

using namespace std;

const int INF = 0x3f7f7f7f;
const int maxN = 20005;
const int step = 10000;//即使多一块也无妨,多出来的一部分最长是step
int need,n,rest;
int dp[maxN],v[maxN],cost[maxN];

int main(){
	cin >> need >> n >> rest;	
	for(int i = 0;i< n;i++){
		cin >> v[i] >> cost[i];			
	}
	fill(dp,dp+maxN,INF);
	dp[0] = 0;
	for(int i = 0;i< n;i++){
		for(int j = need+step ; j >= v[i];j--){
			if(dp[j-v[i]]!=INF){//如果dp[j-v[i]]可达
				dp[j] = min(dp[j],dp[j-v[i]]+cost[i]);
			}
		}
	}
	int res = INF;
	for(int i = need;i<=need+step;i++){ //这里任何一个i都是满足条件的
		if(dp[i]!=INF)
			res = min(dp[i],res);
	}
	if(res > rest)
		cout << "Impossible\n";
	else
		cout << rest - res<<"\n";
}