1. 程式人生 > >【題解】數字遊戲

【題解】數字遊戲

ios 想要 題目 ret efi msu 例如 www i++

題目描述

  丁丁最近沈迷於一個數字遊戲之中。這個遊戲看似簡單,但丁丁在研究了許多天之中之後卻發覺,原來在簡單的規則下想要贏得這個遊戲並不那麽容易。遊戲是這樣的,在你面前有一圈整數(一共n個),你要按順序將其分為m個部分,各部分內的數字相加,相加所得的m個結果對10取模後再相乘,最終得到一個數k。遊戲的要求是使你所得的k最大或者最小。

  例如,對於下面這圈數字(n=4,m=2):

技術分享圖片

  當求最小值時,為((2-1)mod10)×((4+3)mod10)=1×7=7,當求最大值時,為((2+4+3)mod10)×(-1mod10)=9×9=81。特別值得註意的是,無論是負數還是整數,對10取模的結果均為非負值。丁丁請你編寫程序幫他贏得這個遊戲。

輸入格式

  第一行有兩個整數,n(1≤n≤50)和m(1≤m≤9)。

  以下n行,每行有一個整數,其絕對值不大於104104,按順序給出圈中的數字,首尾相接。

輸出格式

  兩行,各包含一個非負整數。第一行是你的程序得到的最小值,第二行是最大值。

輸入樣例

4 2

4

3

-1

2

輸出樣例

7

81

題解

  區間dp模板題,只需要在多開一重狀態表示當前分成了幾個部分,最後取分成$m$個部分的最優解即可。

技術分享圖片
#include <iostream>
#include <cstring> 
#define
MAXN 51 #define MAXM 10 #define MOD 10 using namespace std; int n, m; int a[MAXN][MAXN]; long long f[MAXN][MAXN][MAXM]; long long ans; int main() { cin >> n >> m; for(register int i = 1, tmp; i <= n; i++) { cin >> tmp; for(register int
j = 1; j <= n; j++) { for(register int k = 1; k <= n; k++) { if((j <= i && k >= i) || (j > k && (j <= i || k >= i))) { a[j][k] = ((a[j][k] + tmp) % MOD + MOD) % MOD; } } } } memset(f, 127, sizeof f); ans = 0xffffffffff; for(register int k = 0; k < n; k++) { for(register int i = 1; i <= n; i++) { f[i][(i + k - 1) % n + 1][1] = a[i][(i + k - 1) % n + 1]; for(register int j = 2; j <= min(k + 1, m); j++) { for(register int l = i; l < i + k; l++) { f[i][(i + k - 1) % n + 1][j] = min( f[i][(i + k - 1) % n + 1][j], f[i][(l - 1) % n + 1][min(l - i + 1, j - 1)] * f[l % n + 1][(i + k - 1) % n + 1][max(j - (l - i + 1), 1)]); } } } } for(register int i = 1; i <= n; i++) { ans = min(ans, f[i][((i + n - 2) % n + 1)][m]); } cout << ans << endl; memset(f, 0, sizeof f); ans = 0; for(register int k = 0; k < n; k++) { for(register int i = 1; i <= n; i++) { f[i][(i + k - 1) % n + 1][1] = a[i][(i + k - 1) % n + 1]; for(register int j = 2; j <= min(k + 1, m); j++) { for(register int l = i; l < i + k; l++) { f[i][(i + k - 1) % n + 1][j] = max( f[i][(i + k - 1) % n + 1][j], f[i][(l - 1) % n + 1][min(l - i + 1, j - 1)] * f[l % n + 1][(i + k - 1) % n + 1][max(j - (l - i + 1), 1)]); } } } } for(register int i = 1; i <= n; i++) { ans = max(ans, f[i][((i + n - 2) % n + 1)][m]); } cout << ans; return 0; }
參考程序

【題解】數字遊戲