有一個由數字 1 , 2 , … , 9 組成的數字串(長度不超過 200 ),問如何將 M(M<=20) 個加號 (“+”) 插入到這個數字串中,使所形成的算術表達式的值最小。請編一個程序解決這個問題。 注意: 加號不能加在數字串的最前面或最末尾,也不應有兩個或兩個以上的加號相鄰。 M 保證小於數字串的長度。 例如:數字串 79846 ,若需要加入兩個加號,則最佳方案為 79+8+46 ,算術表達式的值 133 。
【輸入格式】
數字串在輸入文件的第一行行首(數字串中間無空格且不折行),M的值在輸入文件的第二行行首。
【輸出格式】
輸出所求得的最小和的精確值。
【輸入輸出樣例】
輸入:
exam4.in
82363983742
3
輸出:
exam4.out
2170
【分析】
動態規劃,類似於『NOIP2000 乘積最大』。
狀態設定:
F[i,j] :前i個數添加j個乘號的最小和
Num[i,j]:原數中第i個數到第j個數組成的新數。
邊界狀態:F[i,0]=Num[1,i]
狀態轉移方程: F[i,j]=Min{F[k,j-1]+Num[k+1,i]}
目標狀態:F[N,K]
由於數據比較大,所以需要高精度計算。
【我的代碼】
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int SIZE=201; int K; int N; typedef unsigned short int usint; struct hugeint { usint len,num[SIZE]; }; hugeint Num[201][201]; hugeint F[201][21]; void print(hugeint a) { int i; for (i=a.len;i>=1;i--) printf("%d",a.num[i]); printf("\n"); } hugeint add(hugeint a,hugeint b) { int i; hugeint ans; memset(ans.num,0,sizeof(ans.num)); if (a.len>b.len) ans.len=a.len; else ans.len=b.len; for (i=1;i<=ans.len;i++) { ans.num[i]+=(a.num[i]+b.num[i]); ans.num[i+1]+=ans.num[i]/10; ans.num[i]%=10; } if (ans.num[ans.len+1]>0) ans.len++; return ans; } bool over(hugeint a,hugeint b) { int i; if (a.len<b.len) return false; if (a.len>b.len) return true; for (i=a.len;i>=1;i--) { if (a.num[i]<b.num[i]) return false; if (a.num[i]>b.num[i]) return true; } return false; } void init() { hugeint tmp; memset(tmp.num,0,sizeof(tmp.num)); char str[201]; scanf("%s\n%d\n",&str,&K); int len=strlen(str); tmp.len=len; N=len; for (int i=0;i<len;i++) { tmp.num[i+1]=str[i]-'0'; } for (int i=1;i<=len;i++) { for (int j=i;j<=len;j++) { memset(Num[i][j].num,0,sizeof(Num[i][j].num)); Num[i][j].len=j-i+1; int top=Num[i][j].len; for (int k=i;k<=j;k++) { Num[i][j].num[top]=tmp.num[k]; top--; } /* printf("%d %d %d ",i,j,Num[i][j].len); print(Num[i][j]); */ } } } void dynamic() { for (int i=1;i<=N;i++) F[i][0]=Num[1][i]; for (int j=1;j<=K;j++) { for (int i=1;i<=N;i++) { for (int k=1;k<=N;k++) F[i][j].num[k]=9; F[i][j].len=N; for (int k=1;k<=i-1;k++) { hugeint temp=add(F[k][j-1],Num[k+1][i]); if(over(F[i][j],temp) ) { F[i][j]=temp; } } } } print(F[N][K]); } int main() { freopen("exam4.in","r",stdin); freopen("exam4.out","w",stdout); init(); dynamic(); return 0; }
沒有留言:
張貼留言