数字游戏 (vijos 1218)
2015-03-21 13:18
218 查看
转自:/article/2421035.html
Description
【问题描述】
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。 例如,对于下面这圈数字(n=4,m=2):
![](http://zuojie.3322.org:88/soj/problem/2113/pic1.jpg)
当要求最小值时,((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
Sample Output
Source NOIP2003普及组
状态:
把环拆成链,枚举开始位置
d[i][j]表示前i个数分成j部分的最优值
状态转移方程:
d[i][j]=opt(d[i][j],d[k][j-1]*(((s[i]-s[k])%10+10)%10))
s[i]是前i个数的和
边界:
d[0][0]=1;
d[i][1]=((s[i]%10+10)%10)
代码:
[cpp] view
plaincopy
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,Max,Min,s[55],d[55][10],dp[55][10];
void DP(int a[])
{
int i,j,k;
for(i=1;i<=n;i++)
s[i]=s[i-1]+a[i];
for(i=0;i<=n;i++)
for(j=0;j<=m;j++)
{
d[i][j]=0;
dp[i][j]=-1u>>1;
}
d[0][0]=dp[0][0]=1;
for(i=1;i<=n;i++)
d[i][1]=dp[i][1]=(s[i]%10+10)%10;
for(j=2;j<=m;j++)
for(i=j;i<=n;i++)
for(k=j-1;k<i;k++)
{
d[i][j]=max(d[i][j],d[k][j-1]*(((s[i]-s[k])%10+10)%10));//第k+1个数到第i个数分到第j部分
dp[i][j]=min(dp[i][j],dp[k][j-1]*(((s[i]-s[k])%10+10)%10));
}
Max=max(Max,d
[m]);
Min=min(Min,dp
[m]);
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
int i,j,a[105];
Max=0;
Min=-1u>>1;
for(i=1;i<=n;i++)
{
scanf("%d",a+i);
a[n+i]=a[i];
}
for(j=0;j<n;j++)
DP(a+j);
printf("%d/n%d/n",Min,Max);
}
}
Description
【问题描述】
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。 例如,对于下面这圈数字(n=4,m=2):
![](http://zuojie.3322.org:88/soj/problem/2113/pic1.jpg)
当要求最小值时,((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 4 2 4 3 -1 2
Sample Output
7 81 7 81
Source NOIP2003普及组
状态:
把环拆成链,枚举开始位置
d[i][j]表示前i个数分成j部分的最优值
状态转移方程:
d[i][j]=opt(d[i][j],d[k][j-1]*(((s[i]-s[k])%10+10)%10))
s[i]是前i个数的和
边界:
d[0][0]=1;
d[i][1]=((s[i]%10+10)%10)
代码:
[cpp] view
plaincopy
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,Max,Min,s[55],d[55][10],dp[55][10];
void DP(int a[])
{
int i,j,k;
for(i=1;i<=n;i++)
s[i]=s[i-1]+a[i];
for(i=0;i<=n;i++)
for(j=0;j<=m;j++)
{
d[i][j]=0;
dp[i][j]=-1u>>1;
}
d[0][0]=dp[0][0]=1;
for(i=1;i<=n;i++)
d[i][1]=dp[i][1]=(s[i]%10+10)%10;
for(j=2;j<=m;j++)
for(i=j;i<=n;i++)
for(k=j-1;k<i;k++)
{
d[i][j]=max(d[i][j],d[k][j-1]*(((s[i]-s[k])%10+10)%10));//第k+1个数到第i个数分到第j部分
dp[i][j]=min(dp[i][j],dp[k][j-1]*(((s[i]-s[k])%10+10)%10));
}
Max=max(Max,d
[m]);
Min=min(Min,dp
[m]);
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
int i,j,a[105];
Max=0;
Min=-1u>>1;
for(i=1;i<=n;i++)
{
scanf("%d",a+i);
a[n+i]=a[i];
}
for(j=0;j<n;j++)
DP(a+j);
printf("%d/n%d/n",Min,Max);
}
}
相关文章推荐
- vijos1218 数字游戏 (环形dp)
- Vijos_1218_数字游戏_(划分型动态规划+环状动态规划)
- 【Vijos】1218 数字游戏
- vijos 1218 数字游戏(环形dp)
- 【动态规划】Vijos P1218 数字游戏(NOIP2003普及组)
- 【动态规划】Vijos P1218 数字游戏(NOIP2003普及组)
- Vijos P1218 数字游戏(动态规划,环形DP)
- 牛牛举办了一场数字游戏,有n个玩家参加这个游戏,游戏开始每个玩家选定一个数,然后将这个数写在纸上(十进制数,无前缀零),然后接下来对于每一个数字将其数位按照非递减顺序排列,得到新的数,新数的前缀零将被
- 【模拟】洛谷 P1427 小鱼的数字游戏
- 挣值管理不是搞数字游戏(3)——进阶指标:CV、SV、CPI、SPI、EAC
- Python_猜数字游戏_初次尝试(遗留问题:猜错后程序自动循环执行未实现)---加入循环搞定
- 简单的数字顺序表游戏
- Fzu 2135 数字游戏【贪心】
- python练手程序(1)—— 猜数字游戏
- 101个shell脚本 猜数字游戏代码
- 数字生成游戏 纪中2570 bfs
- WF4.0实战(九):猜数字游戏,测下你的智力
- codevs动态规划 数字游戏
- 蓝桥杯 数字游戏【规律】
- 一个简单猜数字游戏的实现(二)