【NOIP模拟】艾比所特

来源:互联网 发布:win10qq远程控制mac 编辑:程序博客网 时间:2024/04/29 06:30

Description

阿良良木历将要迎来人生(不,是吸血鬼生涯)的第二次战斗——与身为人类和吸血鬼混血儿的艾比所特在直江津高中的操场solo,以取回Heartunderblade的左脚。
艾比所特个子不大,却单手扛着一副形状比自己大三倍,重量是他体重乘三次方的巨大十字架。吸血鬼是怕十字架的,所以历要远远地躲着。更麻烦的是艾比所特能变成雾气,历攻击不到他,他却因为是混血儿,吸血鬼的弱点降到了mininum,可以碰十字架。直到历用沙子使艾比所特显形,历才获得胜利。
可以把直江津高中的操场看成排成一条直线的n个点,其中第i个点位于数轴上的位置x[i]。如果从i跳到j,首先要花费时间|x[j]-x[i]|。假如i

Solution

这道题,题意很奇怪,字句间暗藏玄机。
我开始还以为是只用找一个环,那么就是值最大的欧拉回路。
然后其实是可以有很多个简单环的。

那么就有一个很显然的性质

每个点的入度和出度只有1。
我们设f[i][j][k]表示做到第i个点,在1~i之间有j个点的还没有出度,有k个点还没有入度。
我们考虑从第i个点推向第i+1个点。
第一种情况:前i个点有一个点连向第i+1个点,第i+1个点又连回来——>f[i+1][j1][k1]=max(f[i+1][j+1][k+1],f[i][j][k]+x[i+1]2+a[i+1]+c[i+1]);
第二种情况:前i个点有一个点连向第i+1个点,第i+1个点往后面连——>f[i+1][j][k]=max(f[i+1][j][k],f[i][j][k]+a[i+1]+d[i+1]);为什么j和k没有-1呢?因为推到i+1是又会多一个点的,那么影响j和k的点原本是又会多一个,但是这里会抵消一个,上面的那种情况会抵消两个。
第三种情况:第i+1个点连向前i个点的一个点,i+1后面的点连向第i+1个点——>f[i+1][j][k]=max(f[i+1][j][k],f[i][j][k]+b[i+1]+c[i+1]);
第四种情况:i+1后面的点连向第i+1个点,第i+1个点又连向i+1后面的点——>f[i+1][j+1][k+1]=max(f[i+1][j+1][k+1],f[i][j][k]x[i+1]2+b[i+1]+d[i+1]);这种情况不会抵消。
注意边界条件,前三种情况是在j>0||k>0的时候才能向后推的,因为都与i前面的点有关,前面的点用完了,自然不能连。

缩小空间

我们发现j和k都是同时加减的,所以三维可以合并为二维。
其实还可以继续缩小,当然是滚动啦。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;typedef long long ll;const int maxn=10007;ll i,j,k,l,t,n,m,ans,da;ll x[maxn],a[maxn],b[maxn],c[maxn],d[maxn],p,q;ll f[2][maxn];int main(){    scanf("%lld",&n);    fo(i,1,n)scanf("%lld",&x[i]);    fo(i,1,n)scanf("%lld",&a[i]);    fo(i,1,n)scanf("%lld",&b[i]);    fo(i,1,n)scanf("%lld",&c[i]);    fo(i,1,n)scanf("%lld",&d[i]);    memset(f,128,sizeof(f));da=f[0][0];    f[0][0]=0;p=0;    fo(i,0,n-1){        q=p^1;        fo(j,0,i){            if(f[p][j]==da)continue;            if(j){                f[q][j-1]=max(f[q][j-1],f[p][j]+x[i+1]*2+a[i+1]+c[i+1]);                f[q][j]=max(f[q][j],f[p][j]+a[i+1]+d[i+1]);                f[q][j]=max(f[q][j],f[p][j]+b[i+1]+c[i+1]);              }            f[q][j+1]=max(f[q][j+1],f[p][j]-x[i+1]*2+b[i+1]+d[i+1]);          }        p=p^1;    }    printf("%lld\n",f[p][0]);}
2 0