P1005 [NOIP2007 提高组] 矩阵取数游戏

P1005 [NOIP2007 提高组] 矩阵取数游戏

贪心?假了。

1 4
4 5 0 5

这组样例应该是 5×2+0×4+4×8+5×16=122

你的贪心呢?4×2+5×4+0×8+5×16=108

你还觉得贪心对吗?

正解是区间DP,那怎么做?

我们考虑,每一行之间取数互不影响,所以可以一行一行 DP 进行加和。

这个转移其实也比较好想,因为只能从两头取得分,所以我们设 f[l][r] 为区间 [l,r] 的最大得分:

f[l][r]=max(f[l+1][r]+a[l],f[l][r1]+a[r])×2

为什么 ×2 ?因为题目要求 ×2i ,所以一步步把 2 往上乘就行。

这题要求写高精,但是我不会,所以用 __int128 水

/*
Knowledge : Rubbish Algorithm
Work by :Gym_nastics
Time : O(AC)
*/
#include<bits/stdc++.h>
#define int __int128
using namespace std;
const int N=100;

int read() {
    int x=0,f=0;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) f|=(ch=='-');
    for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch&15);
    return f?-x:x;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10+48);
}

int Ans,n,m,f[N][N];
int calc(int *s){
    memset(f,0,sizeof f);
    for(int len=1;len<=m;len++){
        for(int l=1;l+len-1<=m;l++){
            int r=l+len-1;
            f[l][r]=max(f[l+1][r]+s[l],f[l][r-1]+s[r])*2;
        }
    }return f[1][m];
}
int a[N][N];
signed main() {
   n=read();m=read();
   for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) a[i][j]=read();
   for(int i=1;i<=n;i++) Ans+=calc(a[i]);
   return print(Ans),0;
}

本文作者:Gym_nastics

本文链接:https://www.cnblogs.com/BlackDan/p/16027598.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Gym_nastics  阅读(134)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起