上班之余抽点时间出来写写博文,希望对新接触的朋友有帮助。今天在这里和大家一起学习一下数字字符串
一、标题:
给出一个数字(10,000~100,000,000),把这个数字拆分红4段,怎样使得4段的乘积最小。比如12345拆分红1*2*3*45=270, 10000=1*00*0*0=0。
二、分析:
这是一个型典的DP问题,设假dp[i][j]示表分红i段,且字符串指针动移到第j位时的最小乘积。 则明显i<=j.
num[i][j]是数字中从第i个数字到第j个数字成组的数字。则可以到得DP的态状方程:
dp[i-][j-k]示表当数字分红i-1段,且字符串指针动移第j-k位时的态状,因为(i-1)<=(j-k) ,所以要求k<=j-i+1。
由态状方程很轻易得出对应的结果:
i\j | 1 | 2 | 3 | 4 | 5 |
1 | 1 | 12 | 123 | 1234 | 12345 |
2 | - | 2 | 23 | 234 | 2345 |
3 | - | - | 6 | 68 | 690 |
4 | - | - | - | 24 | 270 |
5 | - | - | - | - | 120 |
本题是分红4段,很轻易到得dp[4][5] 出输结果是:270.
三、代码如下:
#include<stdio.h> #define MAXN ((1<<31)-1) //极大值 char A[10]; int num[10][10]; int dp[10][10]; //将对应字符串的制订置位转换为数整。 int getInt(int i,int j) { int temp=0,k; for(k=i-1;k<=j-1;k++) temp=temp*10+(A[k]-'0'); return temp; } int main() { int i,j,k,len,temp,min; while(scanf("%s",A)!=EOF) { k=0; while(A[k]!='\0') k++; len=k; //取得字符串的长度 if(len<5||len>9) return 0; //长度必须是5到9 for(i=1;i<=len;i++) for(j=i;j<=len;j++) num[i][j]=getInt(i,j); for(j=1;j<=len;j++) dp[1][j]=getInt(1,j); //初始化分割为1时的态状 for(i=2;i<=len;i++) for(j=i;j<=len;j++) { min=MAXN; for(k=1;k<=j-i+1;k++) { temp=dp[i-1][j-k]*num[j-k+1][j]; if(temp<min) min=temp; } dp[i][j]=min; if(j!=len) printf("%d ",dp[i][j]); else printf("%d\n",dp[i][j]); } printf("分红4段时,最小的分割方法是:%d\n",dp[4][len]); } return 0; }
文章结束给大家分享下程序员的一些笑话语录:
警告
有一个小伙子在一个办公大楼的门口抽着烟,一个妇女路过他身边,并对他 说, “你知道不知道这个东西会危害你的健康?我是说, 你有没有注意到香烟 盒上的那个警告(Warning)?”
小伙子说,“没事儿,我是一个程序员”。
那妇女说,“这又怎样?”
程序员说,“我们从来不关心 Warning,只关心 Error”