HDU 5712 很强的DP

来源:互联网 发布:淘宝店铺解封需要钱吗 编辑:程序博客网 时间:2024/05/30 22:52

暴力DP!四位数组记录每个区间最后一次取数包含了左右端点,在每个公差每个长度下的可行性和删除次数
很强的DP,自己想不出来,继续努力,打脸终有日。

代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<string>#include<iomanip>#include<vector>#include<set>#include<map>#include<queue>using namespace std;typedef long long LL;typedef unsigned long long ULL;#define rep(i,k,n) for(int i=(k);i<=(n);i++)#define rep0(i,n) for(int i=0;i<(n);i++)#define red(i,k,n) for(int i=(k);i>=(n);i--)#define sqr(x) ((x)*(x))#define clr(x,y) memset((x),(y),sizeof(x))#define pb push_back#define mod 1000000007const int mxn=33;const int mxx=17;int n,m,xmin,xmax,a[mxn],d[mxn];int mk=0;int dd[mxn][mxn],cnt[mxn][mxn][mxn][mxx],f[mxn][mxn],g[mxn][mxn];int ok[mxn][mxn][mxn][mxx];inline void upd(int l,int r,int a,int b){    if(a>f[l][r])    {        f[l][r]=a;        g[l][r]=b;    }    else if(a==f[l][r]) g[l][r]=min(g[l][r],b);}void solve(){    scanf("%d%d%d%d",&n,&m,&xmin,&xmax);    rep(i,1,n)scanf("%d",&a[i]);    rep(i,1,m)scanf("%d",&d[i]);    mk++;clr(dd,0);clr(ok,0);clr(cnt,0);clr(f,0);clr(g,0);    rep(i,1,n)rep(j,i+1,n)    {        rep(k,1,m)if(a[j]-a[i]==d[k])dd[i][j]=k;    }    rep(len,2,n)for(int l=1,r=l+len-1;r<=n;l++,r++)    {        int d;        rep(x,3,xmax)rep(k,l+1,r-1)if((d=dd[k][r]) && ok[l][k][d][x-1]==mk && ok[k][r][d][2]==mk)        {            ok[l][r][d][x]=mk;            cnt[l][r][d][x]=cnt[l][k][d][x-1]+cnt[k][r][d][2]-1;            if(x>=xmin)upd(l,r,r-l+1,cnt[l][r][d][x]);        }        if((d=dd[l][r]) && f[l+1][r-1]==r-l-1)        {            ok[l][r][d][2]=mk;            cnt[l][r][d][2]=g[l+1][r-1]+1;            if(2>=xmin)upd(l,r,r-l+1,cnt[l][r][d][2]);        }        rep(k,l+1,r)upd(l,r,f[l][k-1]+f[k][r],g[l][k-1]+g[k][r]);    }    printf("%d %d\n",f[1][n],g[1][n]);}int main(){    int T;    scanf("%d",&T);    rep(ii,1,T)    {        printf("Case #%d:\n",ii);        solve();    }    return 0;}
0 0
原创粉丝点击