zoj 2860 Breaking Strings

Breaking Strings

Time Limit: 2 Seconds        Memory Limit: 65536 KB

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;
 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值