P1005 矩阵取数游戏

题意:

对于一个给定的n×m 的矩阵,矩阵中的每个元素 $a_{i,j}$ 均为非负整数。

每次从每行首或尾去一个数字

每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值×$2^i$ ,

其中 i 表示第 i 次取数(从 1 开始编号);

求出取数后的最大得分。

 

区间DP,以f[i][j]代表当前行取完剩下i到j的得分

那么若取头: f[i][j]=f[i+1][j]+num[i]*base[m-(j-i+1)];

  若取尾: f[i][j]=f[i][j-1]+num[j]*base[m-(j-i+1)];

  其中,base[i]代表2的i次方,可以预处理出来

每行ans+=f[i][j];

ans即为答案

 

然而我用贪心,每次取头或尾小的(大的留后面,有$2^i$更大,使得分更多

很明显是错的,a了2个点,因为较小数的旁边可以挨着一个很大的数,(极端)

 

要用高精!!

 

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define olinr return 
#define love_nmr 0
struct stat
{
    int saf[105];
    int len;
    stat()
    {
        memset(saf,0,sizeof saf);
        len=0;
    }
    int &operator [] (int a)
    {
        olinr saf[a];
    }
    friend bool operator < (const stat &a,const stat &b)
    {
        if(a.len<b.len) olinr true;
        if(a.len>b.len) olinr false;
        for(int i=a.len;i>=1;i--)
        {
            if(a.saf[i]<b.saf[i]) olinr true;
            if(a.saf[i]>b.saf[i]) olinr false;
        }
        olinr true;
    }
    friend stat operator * (const stat &a,const stat &b)
    {
        stat c;
        c.len=a.len+b.len+2;
        for(int i=1;i<=a.len;i++)
            for(int j=1;j<=b.len;j++)
            {
                c.saf[i+j-1]+=a.saf[i]*b.saf[j];
                c.saf[i+j]+=c.saf[i+j-1]/10;
                c.saf[i+j-1]%=10;
            }
        while(c.len>1&&c.saf[c.len]==0) c.len--;
        olinr c;
    }
    friend stat operator + (const stat &a,const stat &b)
    {
        stat c;
        c.len=max(a.len,b.len)+2;
        int x=0;
        for(int i=1;i<=c.len;i++)
        {
            c.saf[i]=a.saf[i]+b.saf[i]+x;
            x=c.saf[i]/10;
            c.saf[i]%=10;
        }
        while(c.len>1&&c.saf[c.len]==0) c.len--;
        olinr c;
    }
    void out()
    {
        for(int i=len;i>=1;i--)
            cout<<saf[i];
    }
};
struct node 
{
    int head;
    int tail;
    stat xl[100];
    stat &operator [] (int a)
    {
        olinr xl[a];
    }
    stat front()
    {
        olinr xl[head];
    }
    stat back()
    {
        olinr xl[tail];
    }
    void popfront()
    {
        head++;
    }
    void popback()
    {
        tail--;
    }
}ju[100];
stat base[150];
stat two;
stat f[100][100];
int n,m;
stat ans;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    two.len=1;
    two[1]=2;
    base[0].len=1;
    base[0][1]=1;
    for(int i=1;i<=100;i++)
        base[i]=base[i-1]*two;
    for(int i=1;i<=n;i++)
    {
        ju[i].head=1;
        ju[i].tail=m;
        for(int s,j=1;j<=m;j++)
        {
            cin>>s;
            while(s)
            {
                ju[i][j][++ju[i][j].len]=s%10;
                s/=10;
            }   
        }
    }
    ans.len=1;
    ans[1]=0;
    for(int iq=1;iq<=n;iq++)
    {
        memset(f,0,sizeof f);
        for(int l=0;l<m;l++)
            for(int i=1;i+l<=m;i++)
            {
                int j=i+l;
                int pos=m-l;
                f[i][j]=max(f[i+1][j]+ju[iq][i]*base[pos],f[i][j-1]+ju[iq][j]*base[pos]);
            }
        ans=ans+f[1][m];
    }
    ans.out();
    olinr love_nmr;
}

 

posted @ 2018-08-14 15:51  olinr  阅读(171)  评论(0编辑  收藏  举报