A certain string-processing language allows the programmer to break a string into two pieces. Since this involves copying the old string, it costs n units of time to break a string of n characters into two pieces. Suppose a programmer wants to break a string into many pieces. The order in which the breaks are made can affect the total amount of time used. For example, suppose we wish to break a 20 character string after characters 3, 8, and 10 (numbering the characters in ascending order from the left-hand end, starting from 1). If the breaks are made in left-to-right order, then the first break cost 20 units of time, the second break costs 17 units of time, and the third breaks costs 12 units of time, a total of 49 units of time (see the sample below). If the breaks are made in right-to-left order, then the first break costs 20 units of time, the second break costs 10 units of time, and the third break costs 8 units of time, a total of 38 units of time.
The cost of making the breaks in left-to-right order:
thisisastringofchars (original) thi sisastringofchars (cost:20 units) thi sisas tringofchars (cost:17 units) thi sisas tr ingofchars (cost:12 units) Total: 49 units.
The cost of making the breaks in right-to-left order:
thisisastringofchars (original) thisisastr ingofchars (cost:20 units) thisisas tr ingofchars (cost:10 units) thi sisas tr ingofchars (cost: 8 units) Total: 38 units.
Input:
There are several test cases! In each test case, the first line contains 2 integers N (2<=N<=10000000) and M (1<=M<=1000, M<N). N is the original length of the string, and M is the number of the breaks. The following lines contain M integers Mi (1<=Mi<N) in ascending order that represent the breaking positions from the string's left-hand end.
Output:
For each test case, output in one line the least cost to make all the breakings.
Sample Input:
20 3 3 8 10
Sample Output:
37
题目意思是将长度为n的字符串在制定位置处砍几次,每拆砍一次花费是这一段字符串的长度,求最小花费。
首先将问题转化一下,反过来考虑,用最后剩下的片段合成整体的最小花费,先不考虑效率按一般方法写dp,dp[i][j] 表示从i到j合成一段最小花费,枚举中间分割点就可以求出来,但是再看一下题目中数据大小这样显然是不行的,用sum表示从[i][j]的和,满足四边形不等式条件,但是这个初始条件以及后面k的区间也难以确定,还是得好好理解四边形不等式的过程。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxn 1010
#define inf 0x3f3f3f3f
int n,m;
int num[maxn];
int p[maxn];
int dp[maxn][maxn];
int sum[maxn];
int s[maxn][maxn];
/*
int DP(int x,int y){
if(x==y) return 0;
if(dp[x][y]>0) return dp[x][y];
int ans = inf;
for(int k=x;k<y;k++){
ans = min(ans,DP(x,k) + DP(k+1,y)+sum[y]-sum[x]+p[x]);
}
return dp[x][y] = ans;
}
*/
int main(){
while(cin >> n >>m){
for(int i=1;i<=m;i++) scanf("%d",&num[i]);
sum[0]=p[0]=0;
for(int i=1;i<=m;i++){
p[i] = num[i]-num[i-1];
sum[i] = sum[i-1]+p[i];
}
m++;
sum[m] = sum[m-1] + n-num[m-1];
memset(dp,0x3f3f,sizeof(dp));
for(int i=0;i<=m;i++){
dp[i][i] = 0;
s[i][i] = i;
}
for(int len=2;len<=m;len++){
for(int i=1;i+len-1<=m;i++){
int j=i+len-1;
for(int k=s[i][j-1];k<=s[i+1][j];k++){
if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]){
dp[i][j] = dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
s[i][j] = k;
}
}
}
}
cout << dp[1][m] <<endl;
}
return 0;
}