【luogu1005】【noip2007】 矩阵取数游戏 [区间dp]

P1005 矩阵取数游戏

QAQ我把高精写挂辽

开始考虑的是f[i][j]表示消掉区间i~j然后我没搞好 现在再打好像又知道了 (?????)

按照最最最初的想法f[i][j]表示还剩区间i~j 然后就从大区间转到小区间

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)<(y)?(y):(x)
#define Min(x,y) (x)<(y)?(x):(y)
#define ll long long
#define rg register
#define lson o<<1
#define rson o<<1|1
const int N=100+5,M=1000000+5,inf=0x3f3f3f3f,P=19650827;
const int power=4,base=10000;
int n,m,a[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

struct num{
    int a[N];
    num(){memset(a,0,sizeof(a));}
    num(int x){//低精度转高精度
        memset(a,0,sizeof(a));
        int t=0;
        while(x) a[++t]=x%base,x/=base;
        a[0]=t;
    }
    void print(){
        printf("%d",a[a[0]]);
        for(rg int i=a[0]-1;i>0;--i) printf("%0*d",power,a[i]);
        puts("");
    }
}bas[N],ans,f[N][N];
num operator *(const num &p,const int &q)
{
    num c;
    c.a[0]=p.a[0];
    for(int i=1;i<=p.a[0];++i) c.a[i]=p.a[i]*q;
    for(rg int i=1;i<=c.a[0]+1;++i)
    if(c.a[i]>=base) c.a[i+1]+=c.a[i]/base,c.a[i]%=base;
    if(c.a[c.a[0]+1]) ++c.a[0];
    return c;
}
bool operator <(const num &p,const num &q)
{
    if(p.a[0]<q.a[0]) return 1;
    if(p.a[0]>q.a[0]) return 0;
    for(rg int i=p.a[0];i>0;--i)
    if(p.a[i]!=q.a[i]) return p.a[i]<q.a[i];
    return 0;
}
num operator +(const num &p,const num &q)
{
    num c;
    c.a[0]=max(p.a[0],q.a[0]);
    for(int i=1;i<=c.a[0];++i)
        c.a[i]+=p.a[i]+q.a[i];
    for(int i=1;i<=c.a[0]+1;++i)
    if(c.a[i]>=base) c.a[i+1]+=c.a[i]/base,c.a[i]%=base;
    if(c.a[c.a[0]+1]) ++c.a[0];
    return c;
}

void pre(){
    bas[0]=num(1),ans=num(0);
    for(int i=1;i<=m;++i) bas[i]=bas[i-1]*2;
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),rd(m);
    pre();
    for(int h=1;h<=n;++h){
        num mx=num(0);
        for(int i=1;i<=m;++i) rd(a[i]);
        for(int i=1;i<=m;++i)
        for(int j=1;j<=m;++j) f[i][j]=num(0);
        for(int i=1;i<=m;++i)
        for(int j=m;j>=i;--j)
            f[i][j]=Max(f[i][j],Max(f[i-1][j]+bas[m-j+i-1]*a[i-1],f[i][j+1]+bas[m-j+i-1]*a[j+1]));
        for(int i=1;i<=m;++i) mx=Max(mx,f[i][i]+bas[m]*a[i]);
        ans=ans+mx;
    }
    ans.print();
    return 0;
}

 

posted @ 2019-07-17 19:44  委屈的咸鱼鱼鱼鱼  阅读(132)  评论(0编辑  收藏  举报