洛谷 P1005 矩阵取数游戏

传送门:洛谷 P1005 矩阵取数游戏
算法分析:

每次取数时须从每行各取走一个元素,共 \(n\) 个。经过 \(m\) 次后取完矩阵内所有元素;
每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分\(=\)被取走的元素值\(\times 2^i\),其中 \(i\) 表示第 \(i\) 次取数(从\(1\)开始编号);
游戏结束总得分为 \(m\) 次取数得分之和。

故只要每一次考虑一行上的状况即可。
设现在在第 \(t\) 行, \(dp[i][j]\) 表示最后取 \(i\) , \(j\) 能得到的最大分数值,则这一行的答案就为 \(dp[1][m]\)
\(dp[i][j]=max\{dp[i+1][j]+a[t][i]\times2^{m+i-j},dp[i][j+1]+a[t][j]\times2^{m+i-j}\}\)
其中 \(dp[i][i]=a[i]\times 2^m\)
附注:本题需用高精度,在本题里使用了重载运算符

时间复杂度:\(O(n^3)\)


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxN=100,maxM=80;
struct bign
{
    int len,s[maxN+1];
    bign()
    {
        memset(s,0,sizeof(s));
        len=1;
    }
    bign(int num) {*this=num;}
    bign(const char *num) {*this=num;}
    bign operator=(const int num)
    {
        char s[maxN+1];
        sprintf(s,"%d",num);
        *this=s;
        return *this;
    }
    bign operator=(const char *num)
    {
        for(int i=0;num[i]=='0';num++);
        len=strlen(num);
        for(int i=0;i<len;i++) s[i]=num[len-i-1]-'0';
        return *this;
    }
    bign operator+(const bign &b) const
    {
        bign c; c.len=0;
        for(int i=0,g=0;g||i<max(len,b.len);i++)
        {
            int x=g;
            if(i<len) x+=s[i];
            if(i<b.len) x+=b.s[i];
            c.s[c.len++]=x%10;
            g=x/10;
        }
        return c;
    }
    bign operator+=(const bign &b)
    {
        *this=*this+b;
        return *this;
    }
    void clear() {while(len>1 && !s[len-1]) len--;}
    bign operator*(const bign &b)
    {
        bign c;
        c.len=len+b.len;
        for(int i=0;i<len;i++)
            for(int j=0;j<b.len;j++)
                c.s[i+j]+=s[i]*b.s[j];
        for(int i=0;i<c.len;i++)
        {
            c.s[i+1]+=c.s[i]/10;
            c.s[i]%=10;
        }
        c.clear();
        return c;
    }
    bign operator*=(const bign &b)
    {
        *this=*this*b;
        return *this;
    }
    bool operator<(const bign &b)
    {
        if(len!=b.len) return len<b.len;
        for(int i=len-1;i>=0;i--)
            if(s[i]!=b.s[i]) return s[i]<b.s[i];
        return false;
    }
    bool operator>(const bign &b)
    {
        if(len!=b.len) return len>b.len;
        for(int i=len-1;i>=0;i--)
            if(s[i]!=b.s[i]) return s[i]>b.s[i];
        return false;
    }
    bool operator==(const bign &b)
    {
        return !(*this>b) && !(*this<b);
    }
    bool operator!=(const bign &b)
    {
        return !(*this==b);
    }
    bool operator<=(const bign &b)
    {
        return *this<b || *this==b;
    }
    bool operator>=(const bign &b)
    {
        return *this>b || *this==b;
    }
    string str() const
    {
        string res="";
        for(int i=0;i<len;i++) res=char(s[i]+'0')+res;
        return res;
    }
};
istream& operator>>(istream &in,bign &x)
{
    string s;
    in>>s;
    x=s.c_str();
    return in;
}
ostream& operator<<(ostream &out,const bign &x)
{
    out<<x.str();
    return out;
}
int n,m;
bign a[maxM+1][maxM+1];
bign dp[maxM+1][maxM+1];
bign two[maxM+1];
bign ans;
inline int read();
void work(int);
int main()
{
    n=read(); m=read();
    ans.clear();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>a[i][j];
    two[1]=2;
    for(int i=2;i<=m;i++)
        two[i]=(bign)2*two[i-1];
    for(int t=1;t<=n;t++) work(t);
    cout<<ans;
    return 0;
}
void work(int t)
{
    for(int i=0;i<=maxM;i++)
        for(int j=0;j<=maxM;j++)
            for(int k=0;k<=maxM;k++)
                dp[i][j].clear();
    for(int i=1;i<=m;i++) dp[i][i]=a[t][i]*two[m];
    for(int len=1;len<m;len++)
        for(int i=1;i<=m-len;i++)
        {
            bign x=a[t][i]*two[m-len]+dp[i+1][i+len];
            bign y=a[t][i+len]*two[m-len]+dp[i][i+len-1];
            if(x>y) dp[i][i+len]=x;
            else dp[i][i+len]=y;
        }
    ans+=dp[1][m];
}
inline int read()
{
    char ch=getchar();
    int f=1,num=0;
    while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if(ch=='-') {f=-1; ch=getchar();} 
    while(ch>='0' && ch<='9')
    {
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

猜你喜欢

转载自www.cnblogs.com/ezsyshx/p/10359334.html