zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    利用css实现鼠标经过元素,下划线由中间向两边展开
    盒模型的auto值
    CSS选择器
    CSS类名命名规则
    leetcode 移除元素
    leetcode 有效的括号
    leetcode 罗马数字转整数
    leetcode 回文数
    leetcode 合并两个有序数组
    leetcode 最长公共前缀
  • 原文地址:https://www.cnblogs.com/olinr/p/9475080.html
Copyright © 2011-2022 走看看