luogu 1043 数字游戏(区间dp)
2018-03-24 21:26
204 查看
http://www.elijahqi.win/archives/512
题目描述
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。
例如,对于下面这圈数字(n=4,m=2):
要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
输入输出格式
输入格式:
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。
输出格式:
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
输入输出样例
输入样例#1:
4 2
4
3
-1
2
输出样例#1:
7
81
这个真的超级坑啊,取Mod和c++里的取余不一样,仔细读题的话,可以发现结果加10就可以了
fmin ,fmax分别表示最大和最小 fmin||fmax[i][j][k]表示i~j区间切成k块的答案
使用了一个前缀和来求答案
四重循环分别枚举 切割成的块数,左端点,右端点,中间切的那一刀
注意好边界条件 还有最后计数是i+n1-1
题目描述
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。
例如,对于下面这圈数字(n=4,m=2):
要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
输入输出格式
输入格式:
输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。
输出格式:
输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
输入输出样例
输入样例#1:
4 2
4
3
-1
2
输出样例#1:
7
81
这个真的超级坑啊,取Mod和c++里的取余不一样,仔细读题的话,可以发现结果加10就可以了
fmin ,fmax分别表示最大和最小 fmin||fmax[i][j][k]表示i~j区间切成k块的答案
使用了一个前缀和来求答案
四重循环分别枚举 切割成的块数,左端点,右端点,中间切的那一刀
注意好边界条件 还有最后计数是i+n1-1
#include<cstdio> #include<cstring> #define inf 0x7fffffff inline int work(int x){ int tmp=x%10;if (tmp<0) tmp+=10;return tmp; } inline int max(int x,int y){ return x>y?x:y; } inline int min(int x,int y){ return x<y?x:y; } int fmin[110][110][10],fmax[110][110][10],a[110],n,m; int main(){ freopen("1043.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%d",&a[i]),a[i+n]=a[i];int n1=n;n<<=1; for (int i=1;i<=n;++i) a[i]+=a[i-1]; memset(fmin,0x7f,sizeof(fmin)); for (int i=1;i<=n;++i) for (int j=i;j<=n;++j) fmin[i][j][1]=fmax[i][j][1]=work(a[j]-a[i-1]); for (int k=2;k<=m;++k) for (int i=1;i<=n;++i) for (int j=i+k-1;j<=n;++j) for (int z=i+k-2;z<j;++z){ fmin[i][j][k]=min(fmin[i][j][k],fmin[i][z][k-1]*work(a[j]-a[z])); fmax[i][j][k]=max(fmax[i][j][k],fmax[i][z][k-1]*work(a[j]-a[z])); } int ans1=0,ans2=inf; for (int i=1;i<=n1;++i) ans1=max(fmax[i][i+n1-1][m],ans1),ans2=min(fmin[i][i+n1-1][m],ans2); printf("%d\n%d",ans2,ans1); return 0; }
相关文章推荐
- [luoguP1043] 数字游戏(DP)
- codevs 1085 数字游戏 (环形区间dp+负数取膜)
- 区间dp——[2003NOIP普及组]数字游戏
- luogu1043【2003普及】数字游戏(区间dp)
- luogu P1043 数字游戏
- wikioi1085 - 数字游戏(区间DP或者划分DP)
- uva10891(sum游戏)区间dp
- nyoj 1111 游戏人生(区间DP)
- 2017年浙江工业大学大学生程序设计迎新赛决赛—网络同步赛 G 取数游戏2【区间DP】
- uva 10891 sum游戏(区间dp)
- 区间DPの矩阵取数游戏
- nyoj 1111 游戏人生(区间DP)
- 【划分型DP】数字游戏
- BZOJ 1799 self 同类分布(数位dp,区间各位数字和能整除原数的数字个数)
- vijos 1218 数字游戏(环形dp)
- luogu1880 合并石子(区间dp)
- nyoj 1111 游戏人生(区间DP)
- 1166 矩阵取数游戏[区间dp+高精度]
- 【luogu1005】矩阵取数游戏(高精度+dp)
- POJ 3252 Round Numbers(数位dp,区间中二进制表示时0的个数大于等于1的个数的数字的个数)