nyoj746 http://acm.nyist.net/JudgeOnline/problem.php?pid=746
一道区间dp的题目:
设:a[i][j]为那一串数字中从第i位到第j位的数是多少
f[i][j]为从第一位到第i位分成j段的最大乘积,则有:
f[i][j]=max(f[u][j-1]*a[u+1][i]) (u=1toi-1) u表示分割点
把1~u分成j-1份,其最大乘积就是f[u][j-1],再把剩下的u+1~i的数(a[u+1][i])作为最后一份,两者相乘便可以求出f[i][j].
边界:f[1~n][1]=a[1][1~n]
注意把j放在最外层循环。
代码:
//f[i][j]=max(f[u][j-1]*a[u+1][i]) (u=1toi-1) #include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<stack> #define Size 25 using namespace std; long long T; long long f[Size][Size]; long long a[Size][Size]; char c[Size]; int n,m; int ctoi(char c){ return c-‘0‘; } int stoi(int i,int j){ int num=0; for(int k=j;k>=i;k--){ num+=ctoi(c[k])*pow(10,j-k); } return num; } int main(){ cin>>T; while(T--){ //初始化 memset(f,0,sizeof(f)); memset(a,0,sizeof(a)); //输入 cin>>c+1>>m; n=strlen(c+1); //初始化a数组 for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++){ a[i][j]=stoi(i,j); //cout<<a[i][j]<<‘ ‘; } //cout<<endl; } //边界条件 for(int i=1;i<=n;i++)f[i][1]=a[1][i]; //DP求解 for(int j=2;j<=m;j++){ for(int i=j;i<=n;i++){ for(int u=1;u<i;u++){ if(f[u][j-1]*a[u+1][i] > f[i][j]){ f[i][j] = f[u][j-1]*a[u+1][i]; } } } } //输出最大乘积 cout<<f[n][m]<<endl; } return 0; }
时间: 2024-10-12 15:33:35