【2016-沈阳赛区网络赛-I】区间DP(QSC and Master,hdu 5900)

来源:互联网 发布:linux递归创建目录 编辑:程序博客网 时间:2024/06/06 23:14

http://blog.csdn.net/libin66/article/details/52582506


一开始可以先dp出区间是否可以完全消除。

然后再开始dp答案。

如果可以完全消除,就是区间和。否则枚举分法,把区间分成非空的两个区间,答案为两个区间最优解的和的最小值。


#include<bits/stdc++.h>#define maxn 310using namespace std;typedef long long ll;ll N;ll key[maxn];ll val[maxn];ll sum[maxn];ll dp[maxn][maxn];ll g[maxn][maxn];ll gcd(ll a,ll b){    if(a<b) swap(a,b);    return a%b==0?b:gcd(b,a%b);}int main(){    ll T;    scanf("%I64d",&T);    while(T--)    {        scanf("%I64d",&N);        for(ll i=1;i<=N;i++)            scanf("%I64d",&key[i]);        for(ll i=1;i<=N;i++)        {            scanf("%I64d",&val[i]);            sum[i]=sum[i-1]+val[i];        }        for(ll i=2;i<=N;i+=2)            for(ll j=1;j+i-1<=N;j++)            {                if(i==2) g[j][j+i-1]=gcd(key[j],key[j+i-1])>1;                else                {                    ll& ans=g[j][j+i-1];                    ans=0;                    ans|=gcd(key[j],key[j+i-1])>1&&g[j+1][j+i-2];                    ans|=gcd(key[j],key[j+1])>1&&g[j+2][j+i-1];                    ans|=gcd(key[j+i-2],key[j+i-1])>1&&g[j][j+i-3];                }            }        for(ll i=2;i<=N;i++)            for(ll j=1;j+i-1<=N;j++)            {                dp[j][j+i-1]=0;                if(g[j][j+i-1]) dp[j][j+i-1]=sum[j+i-1]-sum[j-1];                else for(ll k=j;k<j+i-1;k++)                    dp[j][j+i-1]=max(dp[j][j+i-1],dp[j][k]+dp[k+1][j+i-1]);            }        printf("%I64d\n",dp[1][N]);    }    return 0;}


0 0