• noip提高组2007 矩阵取数游戏(luogu p1005)


    原题链接:https://www.luogu.org/problem/show?pid=1005

    DP+高精。

    首先可以证明贪心是错误的,很容易就能找到反例。

    于是考虑DP,对于每一行,首先预处理每个数最后选,然后枚举区间长度,进行区间DP:

    f[i][j]=max(f[i][j+1]+a[i]*2^(m-i-j),f[i+1][j]+a[i]*2^(m-i-j));

    f[i][m]即为每一行能取到的最大值,加入答案即可。

    m<=80,仅仅是2^m就足够炸掉longlong,而luogu上一些人用了_int128这种黑科技。。。

    不是很喜欢用这种不稳定的东西,于是就用结构体写了个朴素的高精,毕竟能够直接传递一个结构体真是太赞了。

    起初只有30分,然后把高精的压位变成4位之后,就A掉了,不得不说这真是压位高精的大胜利。

    #include<cstdio>
    #include<cstring>
    struct num
    {
        int c[105],w;
    }f[105][105],ans;
    num s[105];
    int a[105][105],n,m;
    int max(int x,int y)
    {
        return x>y?x:y;
    }
    void print(num x)
    {
        printf("%d",x.c[x.w]);
        for(int i=x.w-1;i>0;i--)
        {
            if(x.c[i]<1000) printf("0");
            if(x.c[i]<100) printf("0");
            if(x.c[i]<10) printf("0");
            printf("%d",x.c[i]);
        }
    }
    num mul(num x,int y)
    {
        num t;
        t.w=x.w;t.c[t.w+1]=0;
        for(int i=1;i<=x.w;i++) t.c[i]=x.c[i]*y;
        for(int i=1;i<=x.w;i++)
        {
            if(t.c[i]>=10000)
            {
                t.c[i+1]+=t.c[i]/10000;
                t.c[i]%=10000;
            }
        }
        if(t.c[t.w+1]!=0) t.w++;
        return t;
    }
    num add(num x,num y)
    {
        num t;
        int l=max(x.w,y.w);t.w=l;t.c[l+1]=0;
        for(int i=1;i<=l;i++) t.c[i]=x.c[i]+y.c[i];
        for(int i=1;i<=l;i++)
        {
            if(t.c[i]>=10000)
            {
                t.c[i+1]+=t.c[i]/10000;
                t.c[i]%=10000;
            }
        }
        if(t.c[t.w+1]!=0) t.w++;
        return t;
    }
    num getmax(num x,num y)
    {
        if(x.w>y.w) return x;
        if(x.w<y.w) return y;
        for(int i=x.w;i>=1;i--)
        {
            if(x.c[i]>y.c[i]) return x;
            if(x.c[i]<y.c[i]) return y;
        }
        return x;
    }
    int main()
    {    
    //    freopen("testdata.in","r",stdin);
        scanf("%d %d",&n,&m);
        s[0].c[1]=1;s[0].w=1;
        for(int i=1;i<=m;i++) s[i]=mul(s[i-1],2);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
        }
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=m;i++) f[i][i]=mul(s[m],a[k][i]);
            for(int l=1;l<m;l++)
            {
                for(int i=1;i+l<=m;i++)
                {
                    int j=i+l;
                    num ans1=add(f[i][j-1],mul(s[m+i-j],a[k][j]));
                    num ans2=add(f[i+1][j],mul(s[m+i-j],a[k][i]));
                    f[i][j]=getmax(ans1,ans2);
                }
            }
            ans=add(ans,f[1][m]);
    //        print(ans);
    //        printf("
    ");
        }
        print(ans);
        return 0;
    }
  • 相关阅读:
    Bootstrap历练实例:输入框组的大小
    bootstrap历练实例:复选框或单选按钮作为输入框组的前缀或后缀
    bootstrap历练实例:按钮作为输入框组前缀或后缀
    Bootstrap历练实例:垂直的按钮组
    [uiautomator篇][exist 存在,但click错误]
    [python篇][1]configparser 问题汇总
    [python篇][其他] python博客学习汇总
    [uiautomator篇][8] 增加应用读取内置存储卡的权限
    [uiautomator篇] 使用uiautomator需要导入uiautomator库
    [uiautomator篇][9]遇到问题
  • 原文地址:https://www.cnblogs.com/zeroform/p/7697803.html
Copyright © 2020-2023  润新知