你带着你自己挣得的一些金币来到了 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 1≤n≤150000,1≤k≤9,0≤vi,ci≤106。
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(vb−cb−va,0)+va−ca>min(va−ca−vb,0)+vb−cb
拆开
m
i
n
(
)
min()
min(),即
①若
v
b
−
c
b
−
v
a
<
0
v_b-c_b-v_a<0
vb−cb−va<0 且
v
a
−
c
a
−
v
b
<
0
v_a-c_a-v_b<0
va−ca−vb<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
vb−cb−ca>va−ca−cb。当
v
b
−
c
b
<
v
a
<
v
b
v_b-c_b<v_a<v_b
vb−cb<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
vb−cb−va>0 且
v
a
−
c
a
−
v
b
<
0
v_a-c_a-v_b<0
va−ca−vb<0,原式为
v
a
−
c
a
>
v
a
−
c
a
−
c
b
v_a-c_a>v_a-c_a-c_b
va−ca>va−ca−cb 恒成立。而条件可推得
v
a
<
v
b
−
c
b
v_a<v_b-c_b
va<vb−cb。所以
v
a
<
v
b
v_a<v_b
va<vb
③若
v
b
−
c
b
−
v
a
<
0
v_b-c_b-v_a<0
vb−cb−va<0 且
v
a
−
c
a
−
v
b
>
0
v_a-c_a-v_b>0
va−ca−vb>0,原式为
v
b
−
c
a
−
c
b
>
v
b
−
c
b
v_b-c_a-c_b>v_b-c_b
vb−ca−cb>vb−cb 即
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
vb−cb−va>0 且
v
a
−
c
a
−
v
b
>
0
v_a-c_a-v_b>0
va−ca−vb>0,原式为
v
a
−
c
a
>
v
b
−
c
b
v_a-c_a>v_b-c_b
va−ca>vb−cb。但是相加条件,为
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][j−1]−ci,vi−ci))
即不取,前面取过了和开始取。
#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;
}