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的美味度,即对于后手来说 BA>=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 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;}
原创粉丝点击