DTOJ#5227. The Imp

传送门

你带着你自己挣得的一些金币来到了 Ye Olde 魔法商店,希望能买到一些有趣而不凡的魔法物品。商店里用特制的魔法盒子锁着 n n n 个物品,第 i i i 个箱子价格 c i c_i ci 个金币,包含着价值 v i v_i vi 个金币的物品。你知道并清楚的记得所有的 c i c_i ci v i v_i vi

作为一个凡人,你最多只能携带一个魔法物品。因此你希望能得到最有价值的物品。你确实可以这么做,如果没有那个邪恶的魔法生物:小鬼的话。

小鬼可以使用一个魔法咒语,将魔法盒里的东西变成没有魔力和价值的灰尘。当然,它会在你已经购买了一个魔法盒子之后使用这个咒语,这样你就会付了钱却没得到东西。然后你就再买一个又一个…

小鬼的魔力足够他释放 k k k 次咒语,它也可以选择不使用它,允许你拿着这个物品,你可以在任何时候空着手离开(尽管这将成为一个耻辱)。但是,如果你拿到了一个物品,你就必须拿着它离开。你希望最大化你的收益(你获得的物品的价值减去你所花的所有的钱),而小鬼希望它最小。如果你们俩都绝顶聪明并且使用最佳策略,你将会获得多少金币的收益?

输入的第一行包括一个正整数 T T T 表示输入数据组数,每组数据的描述如下:

每组数据第一行有两个整数 n , k n,k n,k,含义如题面所示。

接下来的 n n n 行描述物品的性质,第 i i i 行包括两个整数 v i v_i vi c i c_i ci

对于每一组数据,输出你所可能获得的最大收益。

样例输入
1
3 1
10 5
8 1
20 12
样例输出
7

对于 100 % 100\% 100% 的数据,有 1 ≤ n ≤ 150000 , 1 ≤ k ≤ 9 , 0 ≤ v i , c i ≤ 1 0 6 1\le n\le 150000,1\le k\le 9,0\le v_i,c_i\le 10^6 1n150000,1k9,0vi,ci106

2014-2015 ACM-ICPC, Central Europe Regional Contest (CERC 14)

题解:
首先证明性质:
对于确定的答案集合 a n s [ ] ans[] ans[] a < b a<b a<b v a < v b v_a<v_b va<vb
证明:
考虑交换,即需满足 m i n ( v b − c b − v a , 0 ) + v a − c a > m i n ( v a − c a − v b , 0 ) + v b − c b min(v_b-c_b-v_a,0)+v_a-c_a>min(v_a-c_a-v_b,0)+v_b-c_b min(vbcbva,0)+vaca>min(vacavb,0)+vbcb
拆开 m i n ( ) min() min(),即
①若 v b − c b − v a < 0 v_b-c_b-v_a<0 vbcbva<0 v a − c a − v b < 0 v_a-c_a-v_b<0 vacavb<0,原式为 v b − c b − c a > v a − c a − c b v_b-c_b-c_a>v_a-c_a-c_b vbcbca>vacacb。当 v b − c b < v a < v b v_b-c_b<v_a<v_b vbcb<va<vb 时,显然成立。所以 v a < v b v_a<v_b va<vb
②若 v b − c b − v a > 0 v_b-c_b-v_a>0 vbcbva>0 v a − c a − v b < 0 v_a-c_a-v_b<0 vacavb<0,原式为 v a − c a > v a − c a − c b v_a-c_a>v_a-c_a-c_b vaca>vacacb 恒成立。而条件可推得 v a < v b − c b v_a<v_b-c_b va<vbcb。所以 v a < v b v_a<v_b va<vb
③若 v b − c b − v a < 0 v_b-c_b-v_a<0 vbcbva<0 v a − c a − v b > 0 v_a-c_a-v_b>0 vacavb>0,原式为 v b − c a − c b > v b − c b v_b-c_a-c_b>v_b-c_b vbcacb>vbcb c a < 0 c_a<0 ca<0 恒不成立。当 v a < v b v_a<v_b va<vb 时,条件显然不成立,所以不可能出现。
④若 v b − c b − v a > 0 v_b-c_b-v_a>0 vbcbva>0 v a − c a − v b > 0 v_a-c_a-v_b>0 vacavb>0,原式为 v a − c a > v b − c b v_a-c_a>v_b-c_b vaca>vbcb。但是相加条件,为 c b + c a < 0 c_b+c_a<0 cb+ca<0 恒不成立。所以此情况不可能出现。
证毕。
于是我们把数按 v v v 递增排序,然后采用博弈 D P DP DP
f [ i ] [ j ] f[i][j] f[i][j] 表示 后 i i i 个数,还剩 j j j 次操作的答案。
转移为 f [ i ] [ j ] = m a x ( f [ i + 1 ] [ j ] , m i n ( f [ i + 1 ] [ j − 1 ] − c i , v i − c i ) ) f[i][j]=max(f[i+1][j],min(f[i+1][j-1]-c_i,v_i-c_i)) f[i][j]=max(f[i+1][j],min(f[i+1][j1]ci,vici))
即不取,前面取过了和开始取。

#include<bits/stdc++.h>
#define N 150005
typedef long long ll;	
using namespace std;
inline ll read() {
	char ch;
	while(!isdigit(ch=getchar()));
	ll sum=ch^48;
	while(isdigit(ch=getchar()))sum=(sum<<1)+(sum<<3)+(ch^48);
	return sum;
}
struct node{
	ll v,c;
}a[N];
bool cmp(node x,node y){return x.v<y.v;}
ll f[N][10];
int main(){
	int T=read();
	while(T--){
		int n=read(),k=read();
		for(int i=1;i<=n;++i){
			a[i].v=read(),a[i].c=read();
		}
		sort(a+1,a+1+n,cmp);
		for(int j=0;j<=k;++j)f[n+1][j]=0;
		for(int i=n;i;--i){
			f[i][0]=max(f[i+1][0],a[i].v-a[i].c);
			for(int j=1;j<=k;++j){
				f[i][j]=max(f[i+1][j],min(a[i].v-a[i].c,f[i+1][j-1]-a[i].c));
			}
		}
		printf("%lld\n",f[1][k]);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值