2016ICPC沈阳网赛 HDU 5900 QSC and Master 区间DP

来源:互联网 发布:mysql示例数据库下载 编辑:程序博客网 时间:2024/05/27 09:45

                  在比赛的时候一直是TLE。。。加了平行四边形优化也还是TLE。。。。回来找题解一看发现是自己的状态转移方程写的太差劲了。。。好吧。

                  其实我觉得区间DP有一个例题和这个很相似的,应该很好想到的才是POJ 1651,两者有很大的共同点,所以考虑区间DP。

                  状态转移有两个来源,第一个是假若一个区间[i,j]里面的物品被抽光之后,而且key[i-1]和key[j+1]满足题目条件的话,那么

answer[i-1][i+1]=max(answer[i][j]+value[i]+value[j],answer[i][j])

                 假若在区间里面还剩下几个不能被抽走,区间[i,j]的最大值就相当于两个区间直接拼在一起喽answer[i][j]=max(answer[i][j],answer[i][k]+answer[k+1][j])

                 这就是两个状态转移方程,还是要多多加油呀!以下是代码:

                 Tips:要判断区间[i,j]里的物品是否全都被抽光只需判定answer[i][j]==∑(k=i→ j)value[k]即可,为了这个的判断方便,这里特地的把value做成了前缀和的形式,方便判断


<pre name="code" class="cpp">#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;ll n,t,ans[305][305],key[305],value[305],te;ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}int main(){    scanf("%lld",&t);    while(t--){        scanf("%lld",&n);        for(int i=1;i<=n;++i)            scanf("%lld",&key[i]);        for(int i=1;i<=n;++i)            scanf("%lld",&te),value[i]=value[i-1]+te;        for(int i=1;i<n;++i)            if(gcd(key[i],key[i+1])!=1)               ans[i][i+1]=value[i+1]-value[i-1];        for(int times=3,i=1;times<=n;++times,i=1)        for(int j=i+times-1;j<=n;++j,++i){            for(int k=i;k<j;++k)                ans[i][j]=max(ans[i][j],ans[i][k]+ans[k+1][j]);            if(ans[i+1][j-1]==value[j-1]-value[i]&&gcd(key[i],key[j])!=1)            ans[i][j]=max(ans[i][j],value[j]-value[i-1]);        }        printf("%lld\n",ans[1][n]);        for(int i=1;i<=n;++i)            memset(ans[i]+1,0,sizeof(ll)*n);;    }    return 0;}




0 0
原创粉丝点击