任务

Description

英勇的福克斯有一个使命,从不同的行星收集尽可能多的燃料。有N个行星,第i个行星储存有Ai个单位的燃料。然而,从任何一个其他行星旅行到该行星都需要花费Bi个单位的燃料。不幸的是,燃料是不可再生的,所以当你第二次来到一个行星时,它就没有任何燃料了可以收集。
福克斯从第P个行星出发,当然他们可以立即收集该行星上的燃料。他们然后可以旅行到其他不同的行星。只要他们有足够的燃料,他们可以以任何顺序旅行。最后,他们需要选择一个行星结束旅行,他们的目标是在结束旅行时拥有最多数量的燃料,如果有很多种方法可以实现,他们希望旅行到最多的行星。你能帮助他们么?

Input

输入的第一行包含两个正整数 n , p n , p n,p,表示行星数量,以及出发的星球
接下来 n n n 行,每行包括两个正整数 A [ i ] , B [ i ] A[i] , B[i] A[i],B[i],表示第 i i i 个星球可以收集的燃料,到达第 i i i 个星球需要的燃料

Output

输出的第一行包含一个整数,表示在结束时燃料最多的数量。
第二行包含一个整数,表示在结束时燃料最多的情况下,能够到达的行星的最多数量

Sample Input

5 2
12 12
10 100
8 3
4 5
25 15

Sample Output

25
4

Data

1 ≤ n ≤ 1 0 5 , A [ i ] , B [ i ] ≤ 1 0 4 1\leq n \leq 10^5,A[i],B[i] \leq 10^4 1n105,A[i],B[i]104

Associate

这一道题,我上来5分钟就写完了。
觉得很简单啊,因为不管中间怎么飞行,我最后得到的永远都是每一个不亏本的星球的得到减去支出的值。所以我只需要把所有不亏本星球的差值都加一遍就行了。
但是没有想到一个问题:贷款飞行

还好我考试的时候想到了,不能贷款飞行。就是现在的燃料飞不到某一个星球去的情况。
然后我就改成了接近于正解的算法
拿到了0分
忘判断不能回到最开始的星球了。
获得了0分的好成绩

Solution

所以现在来说一下正解
我们先定义一个ans,用来记录当前的答案。
把所有的星球,根据他们的cost来排一下序(只考虑赚资源的星球,如果这个星球不赚资源就不如不去)

这样的话,我们从最小的cost开始

  • 如果不能到达这个星球(当前ans小于这个星球的cost),那么我们就可以退出循环了。为什么呢?因为,既然这个星球都不能到达,因为整个序列都是排过序的,所以这个星球不能到达,后面比这个星球的cost大的星球就更不能到达了
  • 如果这个星球能到达,我们就考虑把这个星球赚的资源加上

大概就是这样

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>

using namespace std;

inline int read() {
    int x = 0 , f = 1; char ch = getchar();
    for ( ; !isdigit(ch) ; ch = getchar()) if (ch == '-') f = -1;
    for ( ; isdigit(ch) ; ch = getchar()) x = x * 10 + ch - '0';
    return x * f;
}

const int maxn = 1e5 + 10;

struct Node {
	int value , cost;
	
	bool operator < (const Node &k) const {
		return this->cost < k.cost;
	}
}node[maxn];

int cnt;

int ans;

int n , p;

bool vis[maxn];

int tmp;

int main() {
	n = read() , p = read();
	for (int i = 1 ; i <= n ; i ++) {
		int x = read() , y = read();
		if (i == p) {
			ans = x;
		}
		else {
			if (x < y) {
				continue;
			}
			else {
				node[++ cnt].value = x;
				node[cnt].cost = y;
			}
		}
	}
	
	sort(node + 1 , node + cnt + 1);
	
	//for (int i = 1 ; i <= cnt ; i ++) {
	//	cout << node[i].value << " " << node[i].cost << endl; 
	//}
		
	for (int i = 1 ; i <= cnt ; i ++) {
		if (node[i].cost > ans) {
			break;
		}
		
		ans += (node[i].value - node[i].cost);
		tmp ++;
	}
	
	printf("%d\n%d\n" , ans , tmp + 1);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值