数字游戏
2014-01-19 10:53
417 查看
数字游戏
Time Limit:
1 Sec Memory Limit: 128 MB
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。
例如,对于下面这圈数字(n=4,m=2):
![](http://202.121.199.212/JudgeOnline/upload/pimg1015_1.png)
当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏
代码:
注:本题也是环形dp。复杂度O(m*n^3).枚举起点,前j项划分成k堆,可以转换成子问题前kk项划分成k-1堆和mod sum(kk+1->j)。初始条件ans1[j][1]=ans2[j][1]=mod(sum[i+j-1]-sum[i-1]);不要忘了,Max和Min的初值0和inf。
Time Limit:
1 Sec Memory Limit: 128 MB
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。
例如,对于下面这圈数字(n=4,m=2):
![](http://202.121.199.212/JudgeOnline/upload/pimg1015_1.png)
当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏
Input
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。Output
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。Sample Input
4 2 4 3 -1 2
Sample Output
7 81
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <set> #include <map> #define maxn 60 using namespace std; const int inf=-1u>>1; int num[maxn],sum[2*maxn]; //前i项和 int ans1[maxn][maxn],ans2[maxn][maxn]; //ans1表示最小值,ans2表示最大值 int mod(int n) { return n>0?n%10:n%10+10; } int main() { int n,m; //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(cin>>n>>m){ sum[0]=0; int Max=0,Min=inf; for(int i=1;i<=n;i++){ cin>>num[i]; sum[i]=sum[i-1]+num[i]; } for(int i=1;i<=n;i++) sum[n+i]=sum[n+i-1]+num[i]; //for(int i=1;i<=2*n;i++)cout<<sum[i]<<" ";cout<<endl; for(int i=1;i<=n;i++){ //枚举起点 for(int j=1;j<=n;j++) for(int k=1;k<=m;k++){ ans1[j][k]=inf; ans2[j][k]=0; } for(int j=1;j<=n;j++) ans1[j][1]=ans2[j][1]=mod(sum[i+j-1]-sum[i-1]); for(int j=2;j<=n;j++) //从i起前j项 for(int k=2;k<=m;k++) //堆数 for(int kk=1;kk<j;kk++){ //从i起前kk项 if(ans1[kk][k-1]!=inf) ans1[j][k]=min(ans1[j][k],ans1[kk][k-1]*mod(sum[i+j-1]-sum[i+kk-1])); ans2[j][k]=max(ans2[j][k],ans2[kk][k-1]*mod(sum[i+j-1]-sum[i+kk-1])); //cout<<"--"<<ans1[j][k]<<"--"; // cout<<"--"<<ans2[j][k]<<"--"; } Max=max(Max,ans2 [m]); Min=min(Min,ans1 [m]); //cout<<Min<<"**"<<Max<<endl; } cout<<Min<<endl<<Max<<endl; cout<<Min<<endl<<Max<<endl; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) cout<<ans1[i][j]<<" "; cout<<endl; } } return 0; }
注:本题也是环形dp。复杂度O(m*n^3).枚举起点,前j项划分成k堆,可以转换成子问题前kk项划分成k-1堆和mod sum(kk+1->j)。初始条件ans1[j][1]=ans2[j][1]=mod(sum[i+j-1]-sum[i-1]);不要忘了,Max和Min的初值0和inf。