洛谷 P1005 动态规划 大数 区间dp

Problem Description

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n×m的矩阵,矩阵中的每个元素a(i,j)均为非负整数。游戏规则如下:
1 每次取数时须从每行各取走一个元素,共n个。经过m次后取完矩阵内所有元素;
2 每次取走的各个元素只能是该元素所在行的行首或行尾;
3 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值×2^i,其中i表示第i次取数(从1开始编号);
4 游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

Input

输入文件包括n+1行:
第1行为两个用空格隔开的整数n和m。
第2∽n+1行为n×m矩阵,其中每行有m个用单个空格隔开的非负整数。

Output

输出文件仅包含1行,为一个整数,即输入矩阵取数后的最大得分。

Sample Input

2 3
1 2 3
3 4 2

Sample Output

82

Analysis of ideas

k=m-(R-L),可以得到状态转移方程:f[L][R]=max(num[L]*p[k]+dp(L+1,R),dp(L,R-1)+num[R]*p[k])

for(int len=0;len<=m;++len)
        for(int i=1;i+len<=m;++i)
            f[i][i+len]=max(2*f[i+1][i+len]+2*a[i],2*f[i][i+len-1]+2*a[i+len]);

Accepted code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
const int inf = 0x3f3f3f3f;
const int maxn = 200100;
int n,m,k,t;
__int128 a[100][100];
__int128 dp[100][100];

inline int read(){
    int date=0,w=1;char c=0;
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    return date*w;
}

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

void init()
{
    for(int i = 0; i < m; i++)
    {
        for(int j = 0; j < m; j++)
        {
            dp[i][j] = 0;
        }
    }
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    cin(n),cin(m);
    for(int i = 0 ; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            a[i][j] = read();
        }
    }
    __int128 ans = 0;
    for(int i = 0; i < n; i++)
    {   
        init();
        for(int len = 0; len < m; len++)    //区间长度
        {
            for(int k = 0; k+len < m; k++)  //左边界l
            {
                dp[k][k+len] = max(2*dp[k+1][k+len]+2*a[i][k], 2*dp[k][k+len-1]+2*a[i][k+len]);         //有点东西
            }
        }
        ans += dp[0][m-1];
    }
    print(ans);
    return 0;
}
posted @ 2019-12-05 09:54  hezongdnf  阅读(284)  评论(0)    收藏  举报