%%%Claris
这道题的能量只是用来让过当前回合的,而一个人让了,另一个人也可以让回来,两人具体的能量是多少不重要,重要的是A和B能量的差值,如果差值>0,A才可以让过这一回合
用能量值DP的方程很好想,但是能量值太大了没有用
因为糖果的美味度不大,考虑用这个东西DP
令f[i][j]表示当前先手能够在第i~n个糖果拿到至少j的美味度,先后手能量的差最少可以是多少
s[i]表示i~n的糖果美味度之和
对于第i个糖果,假如当前先手是A,后手是B
如果A选择取这个糖果,因为他至少要拿到j的美味度,所以到后手时后手不能在i+1~n拿到s[i]-j+1的美味度,即对于后手来说
B−A>=f[i+1][s[i]−j+1]
不成立
所以有
f[i][j]=−(f[i+1][s[i]−j+1]−1)−r[i]
如果A选择让,首先A-B>=1,然后要保证让了之后,(A-1-(B+r[i]) 至少拿到j的美味度
即
f[i][j]=max(1,f[i+1][j]+r[i]+1)
转移的时候很多是否合法没判挂了很多发…
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e14
using namespace std;
const int maxn = 210;
const int maxv = 210;
int n,m,A,B;
ll r[maxn];
int s[maxn],v[maxn];
ll f[maxn][maxv];
int main()
{
scanf("%d%d%d",&n,&A,&B);
for(int i=1;i<=n;i++)
{
int x,y; scanf("%d%d",&y,&x);
v[i]=x; r[i]=y;
}
for(int i=n;i>=1;i--) s[i]=s[i+1]+v[i];
for(int i=0;i<=v[n];i++) f[n][i]=-inf;
for(int i=v[n]+1;i<=s[1];i++) f[n][i]=inf;
for(int i=n-1;i>=1;i--) for(int j=0;j<=s[i];j++)
{
if(v[i]>=j) f[i][j]=-inf;
else f[i][j]=-(f[i+1][s[i]-j+1]-1)-r[i];
ll tmp=max(1ll,f[i+1][j]+r[i]+1);
if(j<=s[i+1]&&f[i][j]>tmp) f[i][j]=tmp;
}
int ansi;
for(int i=0;i<=s[1]&&(ll)A-B>=f[1][i];i++) ansi=i;
printf("%d %d\n",ansi,s[1]-ansi);
return 0;
}