在n个数字中插入m个加号使表达式的值最小
num[i][j]:位置i到位置j的所表示的数字。
递推:
dp[m][n]表示在n个数字中插入m个加号所能形成的表达式最小值
边界条件:dp[0][i]=num[1][i]
递推公式:dp[i][j]=min(dp[i-1][k]+num[k+1][j])(i<=k<j) k:最后一个加号的位置,i<=k (i-1个加号至少要用i个数字) k<j(最远的位置j-1个数字的后面)
递归:
v(m, n)=min(v(m-1, i)+num(i+1, n)) (i=m.......n-1);
终止条件:if(m==0) return num[1][n];
递推:
#include<bits/stdc++.h>
using namespace std;
int a[50];
int num[50][50];
int dp[50][50];
int main()
{
int n, m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
num[i][i]=a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
num[i][j]=num[i][j-1]*10+a[j];
}
}
for(int i=1;i<=n;i++)
{
dp[0][i]=num[1][i];
}
for(int i=1;i<=m;i++)
{
for(int j=i+1;j<=n;j++)
{
int s=(1<<31)-1;
for(int k=i;k<j;k++)
{
s=min(s, dp[i-1][k]+num[k+1][j]);
}
dp[i][j]=s;
}
}
cout<<dp[m][n]<<endl;
return 0;
}
递归:
#include<bits/stdc++.h>
using namespace std;
int a[50];
int num[50][50];
int dfs[50][50]={{0}};
int v(int m, int n)
{
if(m==0)
{
return num[1][n];
}
int s=(1<<31)-1;
for(int i=m;i<=n-1;i++)
{
if(!dfs[m-1][i])
{
dfs[m-1][i]=v(m-1, i);
}
s=min(s, dfs[m-1][i]+num[i+1][n]);
}
return s;
}
int main()
{
int n, m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
num[i][i]=a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
num[i][j]=num[i][j-1]*10+a[j];
}
}
cout<<v(m, n)<<endl;
return 0;
}