BZOJ5046: 分糖果游戏
来源:互联网 发布:朗朗数码的mac怎么样 编辑:程序博客网 时间:2024/05/22 22:26
%%%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的美味度,即对于后手来说
所以有
如果A选择让,首先A-B>=1,然后要保证让了之后,(A-1-(B+r[i]) 至少拿到j的美味度
即
转移的时候很多是否合法没判挂了很多发…
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 1e14using 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;}
阅读全文
0 0