[Noip2003 PJ] 数字游戏
Description & Range
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共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取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
Input
第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于 $10^4$ ,按顺序给出圈中的数字,首尾相接。
Output
有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
Solution
啊这道题好有水平=.=
第一眼看到这题以为是和石子合并一样水的题,但是蛮多细节要注意的(我也是看题解才知道)
定义 f[0/1][i][j][k] 表示左端点在 i,右端点在 j,分成了 k 个部分的最大/最小乘积
最开始做这题开了五层循环,内层枚举了一下断点和断点两侧分别分成了多少个部分...
后来(抄题解)发现了其实不用枚举两侧分成了多少个部分,因为这会被之前或之后的循环枚举到,打个比方:如果枚举到了左端点是 i,右端点是 j,断点是 k,左边分成了p 个部分,右边分成了 q 个部分。
先明确一下,在合并时,我们只是关注 k+1~j 的前缀和再乘上左边已经乘好的部分, 即 f[i][j][p+q]=max{f[i][j][p+q-1]*(qzh[j]-qzh[k])} 所以是不用管右边分成了几个部分的,直接假设右边分成了一个部分,然后用左边的区间去“吃”右边的区间就好。
Code
// By YoungNeal #include<cstdio> #include<iostream> using namespace std; int n,m; int qzh[105]; int val[105]; int f[2][105][105][15]; int mod(int x){ return (x%10+10)%10; } signed main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&val[i]),val[i+n]=val[i]; for(int i=1;i<=(n<<1);i++) qzh[i]=qzh[i-1]+val[i]; for(int i=1;i<=(n<<1);i++){ for(int j=i;j<=(n<<1);j++) f[0][i][j][1]=f[1][i][j][1]=mod(qzh[j]-qzh[i-1]); } /*愚蠢的五层循环[p]
for(int len=2;len<=(n<<1);len++){ for(int i=1;i<=(n<<1);i++){ int j=i+len-1; if(j>(n<<1)) break; for(int p=i;p<=j;p++){ for(int k=1;k<=min(m,j-i+1);k++){ for(int q=1;q<k;q++){ if(q<=p-i+1&&k-q<=j-p) f[i][j][k]=max(f[i][j][k],f[i][q]+f[p+1][j][k-q]+(qzh[p]-qzh[i-1])*(qzh[j]-qzh[p])); } } } } }*/ for(int i=2;i<=m;i++){ for(int l=1;l<=(n<<1);l++){ for(int r=l+i-1;r<=l+n-1;r++){ //f[l][r][i] f[1][l][r][i]=0x3f3f3f3f; for(int k=l+i-2;k<r;k++){ //k不能=r! f[0][l][r][i]=max(f[0][l][r][i],f[0][l][k][i-1]*mod(qzh[r]-qzh[k])); f[1][l][r][i]=min(f[1][l][r][i],f[1][l][k][i-1]*mod(qzh[r]-qzh[k])); } } } } int maxn=0,minn=0x3f3f3f3f; for(int i=1;i<=n;i++) maxn=max(maxn,f[0][i][i+n-1][m]),minn=min(minn,f[1][i][i+n-1][m]); printf("%d\n%d",minn,maxn); return 0; }
- NOIP 2003 Senior 3 - 加分二叉树
- NOIP 2003 普及组 数字游戏
- Cpp环境【Code[VS]1084】【NOIP2003普及组】乒乓球
- 【动态规划】[NOIP2003]加分二叉树
- NOIP 2003 侦探原理 大模拟+枚举
- NOIP2003 传染病控制 【搜索 + 卡时】
- noip2003 传染病防治
- [NOIP2003]加分二叉树【动态规划】
- 【NOIP2003提高组T4】传染病控制-DFS剪枝
- Noip2003加分二叉树题解
- NOIP2003(洛谷 P1038 )神经网络 COGS 104
- luogu1044 noip2003 栈
- noip2003 侦探推理 (字符串处理)
- 【树形DP】[NOIP2003]加分二叉树
- 【noip2003】传染病控制
- [NOIP 2012PJ]文化之旅 Flyod
- [NOIP 2003] 传染病控制:创造性地DFS,最优性剪枝
- 洛谷 1041 [NOIP2003] 传染病控制 dfs
- [noip2005pj] 校门外的树
- [noip2001pj] 装箱问题