SGU_528_Dragons and Princesses_贪心

困的要死,头疼,一会还得去上哔狗的计算机组成。


题意:

一个骑士进行一场线性路线的历险,除了他所在的第一格,从第二格到第n格,每一格要么有一个公主,有一个魅力值p,或者有一条恶龙,有金钱d。骑士每次面对一条恶龙,都可以选择:杀死它得到所有金钱,或者不和它动手。其实每次遇到一个公主,如果他杀死的龙的数量大于等于公主的魅力值,公主就会求婚他就把持不住结束了历险。骑士想娶到最后一格的公主(最后一格保证有公主),并且他获得的金钱最多,问最多获得多少,杀死哪些龙。



Input

The first line of the input contains a single integer n (2 ≤ n ≤ 2·10 5) — the number of cells. The next n-1 lines describe cells from 2 to n.

If the cell number i contains a dragon, the i-th line of the input contains letter "
d
" followed by a single integer g i (1 ≤ g i ≤ 10 4) — the number of coins the dragon keeps. The letter and the integer are separated by a single space.

If the cell number i contains a princess, the i-th line of the input contains letter "
p
" followed by a single integer b i (1 ≤ b i ≤ 2·10 5) — the beauty of the princess. The letter and the integer are separated by a single space. It is guaranteed that the last cell contains a princess.

Output

On the first line of the output print a single integer — the maximum number of gold coins the Knight can collect. On the second line print a single integer k — the number of dragons to kill. The third line should contain k integers — the numbers of the cells where the Knight should kill a dragon. The cell numbers should be printed in the increasing order.

If there are several optimal solutions, output any of them. If the Knight can't marry his beloved princess, just print
-1
in the first line of the output.


比赛的时候没有想到这个问题有贪心性质,在用DP做,结果做完发现不能存储杀死哪些龙,时间又差不多了,就没做了。其实就是尽可能杀死更多的龙,但数量不能使骑士过早嫁出去,在上面的要求下,就要优先剔除金钱少的龙选择不杀。用一个优先队列维护要杀的龙,每次遇到一个公主(不是最后一个),就开始剔除知道名单上的龙数量少于公主魅力值,最后把名单上的龙都杀掉,算一算娶不娶的到最后一个公主,得出答案。


代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
#define mxn 200010
int n;
int rec[mxn];
struct node{
	int idx,val;
	node(int a,int b){	idx=a,val=b;	}
	bool operator < (const node& rgt)const{
		return val>rgt.val;
	}
};
priority_queue<node> pq;
int main(){
	while(~scanf("%d",&n)){
		while(!pq.empty())	pq.pop();
		char eat[2];
		int a;
		for(int i=2;i<n;++i){
			scanf("%s%d",eat,&a);
			if(eat[0]=='p')	while(pq.size()>=a)
				pq.pop();
			else	pq.push(node(i,a));
		}
		scanf("%s%d",eat,&a);
		int ans=0,cnt=0;
		while(!pq.empty()){
			node tem=pq.top();
			ans+=tem.val;
			rec[cnt++]=tem.idx;
			pq.pop();
		}
		sort(rec,rec+cnt);
		if(cnt<a)	puts("-1");
		else{
			printf("%d\n%d\n%d",ans,cnt,rec[0]);
			for(int i=1;i<cnt;++i)
				printf(" %d",rec[i]);
			puts("");
		}
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值