一道区间dp(没有环的合并石子)&一道分段dp(乘积最大)
乘积最大:
今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ(爬)也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:
设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:
有一个数字串:312, 当N=3,K=1时会有以下两种分法:
1) 3*12=36
2) 31*2=62
这时,符合题目要求的结果是:31*2=62
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。
设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:
有一个数字串:312, 当N=3,K=1时会有以下两种分法:
1) 3*12=36
2) 31*2=62
这时,符合题目要求的结果是:31*2=62
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。
输入描述:
第一行共有2个自然数N,K(6 ≤ N ≤ 40,1 ≤ K ≤ 6)
第二行是一个长度为N的数字串。
输出描述:
输出所求得的最大乘积(一个自然数)
dp数组 : dp[i][j]表示前i个数用了j个乘号进行计算
状态转移方程:dp[i][j] = max(dp[i][j],dp[w][j-1] * tmp);tmp是 第w+1位 ~ 第i位拼成的数字
#include<bits/stdc++.h> using namespace std; # define ll long long const int maxn = 2e3+100; ll dp[maxn][maxn]; char str[maxn]; int main() { int n,k; scanf("%d %d",&n,&k); scanf("%s",str+1); int len=strlen(str+1); ll tmp=0; for(int i=1; i<=len; i++) { tmp=tmp*10+(str[i]-'0'); dp[i][0]=tmp; }//初始化 for(int i=1; i<=len; i++)//前i位 { for(int j=1; j<= min(k,i-1); j++)//用了j个乘号 { for(int w=1; w<i; w++)//枚举乘号位置 {//这里会出现一种情况:i太大了,因此后面不能加入m个乘号,因此需要判断后半段区间中能放入多少个乘号 ll tmp=0; for(int jj=w+1; jj<=i; jj++)//因为w是在上一个区间中处理的,因此当前区间中从w+1开始枚举 { tmp=tmp*10+(str[jj]-'0'); }//处理出要乘进去的数 dp[i][j]=max(dp[i][j],dp[w][j-1]*tmp);//状态转移(把小区间乘到大区间中) } } } printf("%lld\n",dp[len][k]);//输出 return 0; }
合并石子(链状):把洛谷合并石子从环状改为链状(那个蓝题的链状合并石子要用Garsiawachs算法)
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; int dp[1005][1005], n, sum[4004], a; int INF = 0X3f3f3f; int main() { scanf("%d", &n); memset(dp,INF,sizeof(dp)); for(int i = 1;i <= n;i++) { scanf("%d", &a); sum[i] = sum[i-1] + a; dp[i][i] = 0; } for(int len = 1;len <= n;len++)//枚举区间长度 { for(int j = 1;j+len <= n+1;j++)//枚举区间起点 { int ends = j + len - 1;//枚举区间结尾 for(int i = j;i <= n;i++)//枚举区间dp断点 { dp[j][ends] = min(dp[j][ends],dp[j][i] + dp[i+1][ends] + sum[ends] - sum[j-1]); } } } printf("%d", dp[1][n]); return 0; } //7 13 7 8 16 21 4 18

浙公网安备 33010602011771号