Vijos P1218 數字遊戲(動態規劃,環形DP)

P1218數字遊戲

描述

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

格式

輸入格式

輸入文件第一行有兩個整數,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有個整數,其絕對值不大於104,按順序給出圈中的數字,首尾相接。

輸出格式

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

樣例1

樣例輸入1[複製]

4 2
4
3
-1
2

樣例輸出1[複製]

7
81

限制

各個測試點1s

提示

DP!^_^

思路

將4個數分成2份,每一份求數字和,然後將兩個數字和相乘,求一個最小值和一個最大值
四個數爲4,3,-1,2
最小值的劃分:(4+3)*(-1+2)=7
最大值的劃分:(2+4+3)*(-1+10)=81

注意:
數字是環狀的,所以最後一個2與第一個4是相連的,在編程實現時,將環狀改成鏈狀,也就是加長一倍,即:
4,3,-1,2,4,3,-1,2
這樣就有(2+4+3)

負數的取模,可惜寫成加模,-1%10=9,即(-1+10)%10=9

破環爲鏈時,因爲斷點不同,就會得到不同的鏈,比如
3,-1,2,4,3,-1,2,4
-1,2,4,3,-1,2,4,3
……
因此要在最外層循環實現不同的位置斷開

思路

#include <iostream>
#include <cstring>
#define N 102
#define M 10
#define MAX 0x7f7f7f7f
using namespace std;
int n,m,i,j,k,t,maxx,minn=MAX;
int a[N],sum[N];
int f[N][M],g[N][M];
int main()
{
	cin>>n>>m;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
		a[i+n]=a[i];		//將數組加長一倍,實現破環爲鏈 
	}
	for(i=1;i<=n+n;i++)
		sum[i]=sum[i-1]+a[i];		//前i個數的和 
	for(t=0;t<n;t++)				//將環從第t位斷開 
	{
		memset(f,0,sizeof(f));
		memset(g,14,sizeof(g));
		for(i=1;i<=n;i++)			//前i位數 
		{
			f[i+t][1]=g[i+t][1]=((sum[i+t]-sum[t])%10+10)%10;	//分成一份 
			for(j=2;j<=min(i,m);j++)							//分成j份 
				for(k=j-1;k<i;k++)
				{
					f[i+t][j]=max(f[i+t][j],f[k+t][j-1]*(((sum[i+t]-sum[k+t])%10+10)%10));
					g[i+t][j]=min(g[i+t][j],g[k+t][j-1]*(((sum[i+t]-sum[k+t])%10+10)%10));
				}
		}
		maxx=max(f[n+t][m],maxx);
		minn=min(g[n+t][m],minn);
	}
	cout<<minn<<'\n'<<maxx<<endl;
	return 0;
}




發佈了56 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章