【每日一题】7月10日精讲—矩阵取数游戏
來源:牛客網:
文章目錄
- 題目描述
- 題解:
- 代碼:
題目描述
帥帥經常跟同學玩一個矩陣取數游戲:對于一個給定的n*m的矩陣,矩陣中的每個元素aij均為非負整數。游戲規則如下:
1.每次取數時須從每行各取走一個元素,共n個。m次后取完矩陣所有元素;
2.每次取走的各個元素只能是該元素所在行的行首或行尾;
3.每次取數都有一個得分值,為每行取數的得分之和,每行取數的得分 = 被取走的元素值 * 2i,其中i表示第i次取數(從1開始編號);
4.游戲結束總得分為m次取數得分之和。 帥帥想請你幫忙寫一個程序,對于任意矩陣,可以求出取數后的最大得分。
輸入描述:
第1行為兩個用空格隔開的整數n和m。 第2~n+1行為n*m矩陣,其中每行有m個用單個空格隔開的非負整數。
輸出描述:
輸出一個整數,即輸入矩陣取數后的最大得分。
示例1
輸入
復制
輸出
復制
說明
第1次:第1行取行首元素,第2行取行尾元素,本次得分為1 * 21 + 2 * 21 = 6
第2次:兩行均取行首元素,本次得分為2 * 22 + 3 * 22 = 20
第3次:得分為3 * 23 + 4 * 23 = 56。
總得分為6 + 20 + 56 = 82
示例2
輸入
復制
輸出
復制
示例3
輸入
復制
輸出
復制
備注:
60%的數據滿足:1 ≤ n, m ≤ 30, 答案不超過1016
100%的數據滿足:1 ≤ n, m ≤ 80, 0 ≤ aij ≤ 1000
題解:
每一行都進行的相同操作,且每一行的操作都互不影響,所以我們可以一行一行的考慮,算出每一行的最佳情況然后求和
這樣就降低難度維度
先看第一行,只能在行首行尾取,如果我們要知道區間[1,m]的最佳情況,就要知道[1,m-1]和[2,n]的最優解,因為是由他倆推過去的,依次類推
dp[i][j]表示i到j區間的最優解
dp[i][j]=min(dp[i+1][j]+2k *a[i] ,dp[i][j-1] +2k *a[j])
由內向外擴展的過程
區間長度為n時k取1,長度每縮短一次k++,(相當于第k次取)
因為我們乘以2是依次增多的,所以每次都乘以2
本題是需要高精度的,當然也可以使用__int128 +快讀快輸 (黑魔法)
代碼:
#include<bits/stdc++.h> using namespace std; #define _t __int128 inline _t read() {_t x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f; } inline void put(_t x) {if(x<0){putchar('-');x=-x;}if(x>9)put(x/10);putchar(x%10+'0'); } _t n,m,res; _t a[103][103],dp[103][104]; _t cul(_t b[]) {for(_t len=1;len<=m;len++){for(_t l=1,r=l+len-1;r<=m;l++,r=l+len-1){dp[l][r]=max(dp[l+1][r]+b[l],dp[l][r-1]+b[r]);dp[l][r]=2*dp[l][r];}} return dp[1][m]; } int 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++){memset(dp,0,sizeof(dp));res+=cul(a[i]);}put(res);return 0; }總結
以上是生活随笔為你收集整理的【每日一题】7月10日精讲—矩阵取数游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 魔兽世界8.0惩戒骑天赋推荐 惩戒骑士怎
- 下一篇: 关于__int128高精度运算