整数拆段(枚举,DP)(AOJ 847)

来源:互联网 发布:java的编程思想是什么 编辑:程序博客网 时间:2024/06/18 04:52

点击打开链接

整数拆段
Description
将一个位数为L的自然数N拆成4段,使各段对应的数的乘积最小。你能编一个程序实现吗?

Input
一个自然数N。

Output
一个整数,最小乘积。

Sample Input
321427

Sample Output
2268

Hint
100%的数据满足:4≤L≤10

思路
直接枚举,分四段

代码示例
#include<bits/stdc++.h>using namespace std; char str[11]; int fun(int s,int e){    int num=0;    for(int i=s;i<=e;++i){        num=num*10+str[i]-'0';    }    //cout<<str[0]<<endl;     return num;} int main(){    cin>>str;    long long min=100000000000000;    //cout<<min<<endl;    int len=strlen(str);    for(int i=1;i<=len-3;++i)        for(int j=i+1;j<=len-2;++j){            for(int k=j+1;k<=len-1;++k){                //cout<<i<<j<<k<<"(⊙o⊙)…"<<endl;                //cout<<fun(0,i-1)<<' '<<fun(i,j-1)<<' '<<fun(j,k-1)<<' '<<fun(k,len-1)<<endl;                if((fun(0,i-1)*fun(i,j-1)*fun(j,k-1)*fun(k,len-1))<min){                    min=fun(0,i-1)*fun(i,j-1)*fun(j,k-1)*fun(k,len-1);                }            }        }    cout<<min<<endl;    return 0;}


优化

如果数的位数增多,枚举显然力不从心

考虑DP思想,利用f数组记录1到所求位数所有的分拆为1到4的最优值

为什么这样能节省时间呢?

因为长度分拆为j位的最优结果f[i][j]满足

f[i][j]=min(f[i][j],f[k][j-1]*a[k+1][i])

其中k<i,a为辅助求值数组


代码示例

#include<bits/stdc++.h>using namespace std;const long long inf=1e11;char s[15];long long a[15][15];long long f[15][5];//优质数组 int len; long long get(int x,int y){long long ans=0;for(int i=x;i<=y;++i) ans=ans*10+(s[i]-'0');return ans;}int main(){scanf("%s",s+1);s[0]='0';len=strlen(s)-1;//准备 for(int i=1;i<=len;++i){for(int j=i;j<=len;++j) a[i][j]=get(i,j);}for(int i=0;i<15;++i)        for(int j=0;j<5;++j)            f[i][j]=inf;for(int j=0;j<5;++j) f[0][j]=1;for(int i=1;i<=len;++i){for(int j=1;j<=4;++j){for(int k=0;k<i;++k){//利用前面的最优值 f[i][j]=min(f[i][j],f[k][j-1]*a[k+1][i]);//a[k+1][i]表示最后一段(k+1到i)的值}}}printf("%lld\n",f[len][4]);return 0;}


1 0
原创粉丝点击