题目如下:
在一个n位整数a(只考虑正整数的情况)中插入r个加号,将它分成r+1个整数,找出一种加号的插入方法,使得这r+1个整数的和最小。
提示:动态规划求解
设f(i,k)表示在前i位数中插入k个加号所得和的最小值,a(i,j)表示从第i个数字到第j个数字所组成的j−i+1(i≤j)位整数值。
为了求f(i,k)的值,考察数字串的前i个数字,设前j(k≤j<i)个数字中已插入k−1个加号的基础上,在第j个数字后插入第k个加号,显然此时的最小和为f(j,k−1)+a(j+1,i)。于是可以得递推关系式:
f(i,k)=min(f(j,k−1)+a(j+1,i)) (k≤j<i)
前j个数字没有插入加号时的值显然为前j个数字组成的整数,因而得边界值为:
f(j,0)=a(1,j) (1≤j≤i)
代码如下:
package 实验测试;
import java.util.Scanner;
public class JS {
public static void main(String args[]) {
int m;
int time;
Scanner scanner = new Scanner(System.in);
System.out.println("请输入整数串的长度以及需要加入的加号的个数");
m = scanner.nextInt();
time = scanner.nextInt();
int a[] = new int[m];
for(int i = 0; i < a.length; i++) {
a[i] = (int)(Math.random()*10);
}
System.out.print("整数串为:");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
JSS b = new JSS();
b.dp(a, time, m);
}
}
class JSS{
void dp(int a[], int t, int m) {
int i,j,d,k,min;
int max = 100;
int O = 10000;
int f[][] = new int[m+1][t+1];
int num[][] = new int[m][m];
for(i = 0; i < m; i++) {
for(j = 0, d = 0; j < m; j++ ) {
if(i > j)
num[i][j] = O;
else{
d = d*10 + a[j];
num[i][j] = d;
}
}
}
for(i = 1; i <= m; i++)
for(j = 0; j<= t; j++) {
if(j >= i)
f[i][j] = O;
else if(j == 0)
f[i][j] = num[0][i-1];
else {
for(min = O, k = 1; k < i; k++) {
f[i][j] = f[i-k][j-1] + num[i-k][i-1];
if(min > f[i][j])
min = f[i][j];
}
f[i][j] = min;
}
}
System.out.println("最小值:"+f[m][t]);
}
}
运行截图如下:
如有错误欢迎指出。