最佳加法表达式
2017-12-24 12:52
337 查看
最佳加法表达式
总时间限制: 1000ms 内存限制: 65536kB描述给定n个1到9的数字,要求在数字之间摆放m个加号(加号两边必须有数字),使得所得到的加法表达式的值最小,并输出该值。例如,在1234中摆放1个加号,最好的摆法就是12+34,和为36
输入有不超过15组数据
每组数据两行。第一行是整数m,表示有m个加号要放( 0<=m<=50)
第二行是若干个数字。数字总数n不超过50,且 m <= n-1输出对每组数据,输出最小加法表达式的值样例输入
2 123456 1 123456 4 12345
样例输出
102 579 15
提示要用到高精度计算,即用数组来存放long long 都装不下的大整数,并用模拟列竖式的办法进行大整数的加法。
算法参考:http://www.cnblogs.com/quintessence/p/7206417.html 使用了高精度
http://www.cnblogs.com/Renyi-Fan/p/6970166.html 没有使用高精度,有详细分析
假定数字串长度是n,添完加号后,表达式的最后一个加号添加在第 i 个数字后面,
那么整个表达式的最小值,就等于在前 i 个数字中插入 m – 1个加号所能形成的最小值,
加上第 i + 1到第 n 个数字所组成的数的值(i从1开始算)。
设V(m,n)表示在n个数字中插入m个加号所能形成
的表达式最小值,那么:
if m = 0
V(m,n) = n个数字构成的整数
else if n < m + 1
V(m,n) = ∞
else
V(m,n) = Min{ V(m-1,i) + Num(i+1,n) } ( i = m … n-1)
Num(i,j)表示从第i个数字到第j个数字所组成的数。数字编号从1开始算。此操作复杂度是O(j-i+1)
总时间复杂度:O(mn2) .(dp二维表已经加号的位置)
1 #include <stdio.h> 2 #include<string.h> 3 4 #define MaxLength 91 5 int m,len,a[MaxLength]; 6 long long count=0; 7 8 void init(char str[],int a[]); 9 void add(int a[],int b[],int c[]); 10 int cmp(int a[],int b[]); 11 void fun(int m,int n,int min[]); 12 void num(int i,int j,int t[]); 13 void output(int minSum[]); 14 15 int main(int argc, char *argv[]) 16 { 17 freopen("003.txt","r",stdin); 18 freopen("003.out","w",stdout); 19 char str[MaxLength]; 20 int minSum[MaxLength]; 21 int i; 22 23 while(scanf("%d%s",&m,str)!=EOF) 24 { 25 init(str,a); 26 len=a[0]; 27 /*printf("%d\n",m); 28 for(i=1;i<=a[0];i++) printf("%d",a[i]); 29 printf("\n");*/ 30 for(i=1;i<MaxLength;i++) { minSum[i]=9; } 31 minSum[0]=MaxLength+4; 32 33 fun(m,len,minSum); 34 output(minSum); 35 } 36 37 /*char str1[20]="1",str2[20]="234"; 38 int aa[25],bb[25],cc[25]; 39 40 init(str1,aa); 41 init(str2,bb); 42 for(int i=0;i<=aa[0];i++) printf("%d",aa[i]);printf("\n"); 43 for(int i=0;i<=bb[0];i++) printf("%d",bb[i]);printf("\n"); 44 add(aa,bb,cc); 45 for(int i=0;i<=cc[0];i++) printf("%d",cc[i]);printf("\n");*/ 46 47 return 0; 48 } 49 50 /******************************************************************************/ 51 /*输入一个字符串str表示高精度正整数 52 将str转换成int数组存储在a[] 53 a[0]存储str代表的数字的位数 54 str正序存储在a[]中 55 */ 56 void init(char str[],int a[]) 57 { 58 int i; 59 //memset(a,0,sizeof(int)*MaxLength); 60 a[0]=strlen(str); 61 for(i=1;i<=a[0];i++) 62 a[i]=str[i-1]-'0'; 63 } 64 /******************************************************************************/ 65 void fun(int m,int n,int min[]) 66 { 67 int i,j,x[MaxLength]={0},y[MaxLength]={0},sum[MaxLength]; 68 //printf("m=%d n=%d\n",m,n); 69 if(m==0) 70 { 71 num(1,n,min); 72 } 73 else if(n<m+1) 74 { 75 for(i=1;i<MaxLength;i++) { min[i]=9;} 76 min[0]=MaxLength+2; 77 } 78 else 79 { 80 for(i=0;i<MaxLength;i++) min[i]=9; 81 min[0]=MaxLength+2; 82 83 for(i=m;i<n;i++) 84 { 85 fun(m-1,i,x); 86 num(i+1,n,y); 87 add(x,y,sum); 88 if(cmp(sum,min)==-1) 89 { for(j=0;j<=sum[0];j++) min[j]=sum[j]; } 90 } 91 } 92 } 93 /******************************************************************************/ 94 void num(int i,int j,int t[]) 95 { 96 count++; 97 //printf("%d\n",count); 98 99 int k; 100 t[0]=j-i+1; 101 for(k=1;i<=j;k++,i++) t[k]=a[i]; 102 } 103 /******************************************************************************/ 104 /* 输入高精度正整数a和b,计算c=a+b */ 105 void add(int a[],int b[],int c[]) 106 { 107 int x=0,i=a[0],j=b[0],k=1; 108 //memset(c,0,sizeof(int)*MaxLength); 109 //这个地方初始化的字节数的解释:c[]从主调函数传过来,c的元素个数未知。 110 //sizeof(c)只能测出一个元素的字节数,而不是整个数组的字节数 111 112 while(i>0&&j>0) 113 { 114 c[k]=a[i]+b[j]+x;//x表示加法的进位 115 x=c[k]/10; //新产生的进位 116 c[k]=c[k]%10; //只保留个位 117 k++; 118 i--; 119 j--; 120 } 121 while(i>0) 122 { 123 c[k]=a[i]+x; 124 x=c[k]/10; 125 c[k]=c[k]%10; 126 k++; 127 i--; 128 } 129 while(j>0) 130 { 131 c[k]=b[j]+x; 132 x=c[k]/10; 133 c[k]=c[k]%10; 134 k++; 135 j--; 136 } 137 c[k]=x; //可能有向更高位的进位 138 if(c[k]==0) k--; 139 c[0]=k; 140 141 for(i=1,j=c[0];i<j;i++,j--) 142 { 143 x=c[i]; c[i]=c[j]; c[j]=x; 144 } 145 } 146 /******************************************************************************/ 147 /* 比较a[]和b[]表示的两个高精度整数的大小,返回1表示a>b,0表示相等,-1表示a<b */ 148 int cmp(int a[],int b[]) 149 { 150 int i; 151 if(a[0]<b[0]) return -1; 152 else if(a[0]>b[0]) return 1; 153 else 154 { 155 i=1; 156 while(i<=a[0]&&a[i]==b[i]) i++; 157 if(i>a[0]) return 0; 158 else if(a[i]<b[i])return -1; 159 else return 1; 160 } 161 } 162 /******************************************************************************/ 163 void output(int minSum[]) 164 { 165 int i; 166 for(i=1;i<=minSum[0];i++) 167 { 168 printf("%d",minSum[i]); 169 } 170 printf("\n"); 171 }
View Code
相关文章推荐
- 最佳加法表达式
- 最佳加法表达式
- 最佳加法表达式(动态规划)
- [PKU暑课笔记] 动态规划(三) 最佳加法表达式 百练2755 POJ3624背包问题
- 最佳加法表达式
- 最佳加法表达式
- 动态规划(3):熟练度练习(POJ 1458、最佳加法表达式、bailian2755、POJ3624、bailian1088)
- 最佳加法表达式(动态规划)
- dp 最佳加法表达式
- 动态规划4--最佳加法表达式
- 递推,动态规划(DP),字符串处理,最佳加法表达式
- 最佳加法表达式(DP)
- 最佳加法表达式(dp)
- 动态规划之最佳加法表达式
- 最佳加法表达式 dp
- 最佳加法表达式
- 动态规划-最佳加法表达式
- 程序设计与算法(二)测验汇总011:最佳加法表达式(DP、高精度)
- 最佳加法表达式
- dp 最佳加法表达式