ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-03-19 19:34:13  阅读:147  来源: 互联网

标签:ch int P1005 times 取数 NOIP2007 贪心 getchar


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

贪心?假了。

1 4
4 5 0 5

这组样例应该是 \(5 \times 2 + 0\times 4+ 4 \times 8 + 5 \times 16 = 122\)

你的贪心呢?\(4 \times 2 + 5 \times 4 + 0 \times 8 + 5 \times 16 = 108\)

你还觉得贪心对吗?

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

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

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

\[f[l][r]=max(f[l+1][r]+a[l],f[l][r-1]+a[r]) \times 2 \]

为什么 \(\times 2\) ?因为题目要求 \(\times 2^i\) ,所以一步步把 \(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;
}

标签:ch,int,P1005,times,取数,NOIP2007,贪心,getchar
来源: https://www.cnblogs.com/BlackDan/p/16027598.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有