标签:10 普及 半边 NOIP2003 int P1043 枚举 INF 棋盘
考察:区间dp
这题就是一维的棋盘分割.
思路:
f[i][j][k]表示将[i,j]区间分为k份得到的最大值.与棋盘分割不同的是,这道题是一维的,所以我们可以只枚举选上半边就可以枚举到所有方案.也可以枚举选下半边,但是注意这道题要预留足够的空间给进一步选择的上半边和下半边,因为memset初始化后,违法情况会爆数据类型.
那么棋盘切割为什么不能只枚举上半边呢?因为这里枚举只枚举到r-1处,在第r行仍能纵向切割.所以需要从下往上枚举.
此外还需要断环成链,枚举每一个长度为n的区间.
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 typedef long long LL; 5 const int N = 110,INF = 0x3f3f3f3f; 6 int m,n,s[N],sum[N],maxn = -INF,minv = INF; 7 int f[N][N][10],g[N][N][10]; 8 int get(int x)//memset对给定空间填充给定值. 9 { 10 return (x%10+10)%10; 11 } 12 void solve() 13 { 14 for(int len=1;len<=n;len++) 15 for(int l=1;l+len-1<=2*n;l++) 16 { 17 int r = l+len-1; 18 for(int k=2;k<=m;k++) 19 for(int t=l;t<r;t++) 20 { 21 if(l+k-2<t) 22 { 23 int p1 = get(sum[r]-sum[t]); 24 f[l][r][k] = max(f[l][t][k-1]*p1,f[l][r][k]); 25 g[l][r][k] = min(g[l][t][k-1]*p1,g[l][r][k]); 26 } 27 if(t+1+k-2<r) 28 { 29 int p2 = get(sum[t]-sum[l-1]); 30 f[l][r][k] = max(f[t+1][r][k-1]*p2,f[l][r][k]); 31 g[l][r][k] = min(g[t+1][r][k-1]*p2,g[t+1][r][k]); 32 } 33 }//如果g[l][r][k] 不够取k份,相乘可能会爆long long(int) 34 } 35 } 36 void init() 37 { 38 memset(f,-1,sizeof f); 39 memset(g,0x3f,sizeof g); 40 for(int len=1;len<=n;len++) 41 for(int l=1;l+len-1<=2*n;l++) 42 { 43 int r = l+len-1; 44 f[l][r][1] = g[l][r][1] = get(sum[r]-sum[l-1]); 45 } 46 } 47 int main() 48 { 49 scanf("%d%d",&n,&m); 50 for(int i=1;i<=n;i++) scanf("%d",&s[i]),s[i+n] = s[i]; 51 for(int i=1;i<=2*n;i++) sum[i] = sum[i-1]+s[i]; 52 init(); 53 solve(); 54 for(int i=1;i<=n;i++) 55 { 56 maxn = max(maxn,f[i][i+n-1][m]); 57 minv = min(minv,g[i][i+n-1][m]); 58 } 59 printf("%d\n%d\n",minv,maxn); 60 return 0; 61 }
标签:10,普及,半边,NOIP2003,int,P1043,枚举,INF,棋盘 来源: https://www.cnblogs.com/newblg/p/14619829.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。