codevs 1166 矩阵取数游戏

1166 矩阵取数游戏

  1. 每一行的取数的策略都是互相独立的,所以只要找到每行取数的方法即可
  2. 如果数据较小的话,就可以利用记忆化的DP:
    设i,j分别为这行的头和尾,那么
    dp[i][j] = max(dp[i+1][j] + a[i] * 2的m次方 , dp[i][j] + a[j] * 2 的m次方)
    但是发现m最大可能为80,那么2的80次方,无疑是要使用高精度的。
    然而在自己的思维区间中总想不出要怎么使用这个高精度,难道要每个dpi,j的值使用一个数组返回,再比较大小??所以还是去看题解了- -
  3. 发现了一个特别好的题解,整体思路就是用一个结构体存储2个long long ,当满足大于一个很大的数时则进位,(这个是因为题目要对这个数值进行分析,才能证明这样的方法可以存储答案,不过最后也有微略提示答案的最大值),足以代表这个最优值,重载运算符+,<, *,即可,虽然自己脑海中也有闪过这样的一种的方法,不过马上被否决了。。自己还是太嫩了。
    下面贴一份题解代码:

       #include<stdio.h>
       typedef long long ll;
       ll MAX=1000000000000000;
       struct bignum{ll p1,p2;}; //p1是一个数的左端,p2是一个数的右端 
       bignum operator+(const bignum a,const bignum b){
        bignum c;
        c.p1=a.p1+b.p1;
        c.p2=a.p2+b.p2;
        if(c.p2>=MAX){
            c.p2-=MAX;
            c.p1++;
        }
        return c;
       }
       int operator<(const bignum a,const bignum b){
        if(a.p1<b.p1)return 1;
        if(a.p1>b.p1)return 0;
        if(a.p2<b.p2)return 1;
        return 0;
       }
       bignum pow2(int x){
        bignum a;
        a.p1=0;
        a.p2=1;
        while(x--)a=a+a;
        return a;
       }
       bignum operator*(const bignum a,const int b){
        bignum c;
        c.p1=a.p1*b;
        c.p2=a.p2*b;
        if(c.p2>=MAX){
            c.p1+=c.p2/MAX;
            c.p2%=MAX;
        }
        return c;
       }
       void  write(const bignum a){
        if(a.p1) printf("%lld%015lld",a.p1,a.p2);
        else printf("%lld",a.p2);
       }
       bignum max(const bignum a,const bignum b){
        return a<b?b:a;
       }
       int main(){
        int a[85],i,j,n,m;
        bignum score,f[85][85];
        score.p1=0;
        score.p2=0;
        scanf("%d%d",&n,&m);
        while(n--){
            for(i=1;i<=m;i++){
                scanf("%d",&a[i]);
                f[i][i]=pow2(m)*a[i];  //最后一个数肯定是第m次取数了 
            }
            for(j=1;j<m;j++)      //第m - j 次取数 ,也就是对应的段长为2.3.4....m 
                for(i=1;i<=m-j;i++)
                    f[i][i+j]=max(f[i+1][i+j]+pow2(m-j)*a[i],f[i][i+j-1]+pow2(m-j)*a[i+j]);
            score=score+f[1][m];
        }
        write(score);
       }
    

4.保存下来,日后再刷一次看是否可以用这种思维较为顺利地敲出实现代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值