SOJ 2775: Breaking Strings

SOJ 2775: Breaking Strings

Description

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

 

 

思路:

这道题可以用动态规划,先写出状态转移方程

f[i][j]=max{f[i][k]+f[k+1][j]}+d[i][j]

需要遍历k取最优值,预计复杂度会达到O(n^3),必然要超时…

观察方程,发现该题与凸四边优化的适用类型方程相似,接下来就是证明dp数组的单调性,列一个简单的比较不等式就可证得(当时是看到蓝色星空上的分类才去用凸四边不等式做的…)

之后的工作就非常简单了,引入决策点记录数组k[][],通过点调性进行优化,决策区间不重叠复杂度降至O(n^3)(其实应该还可以更优的,同样的方法不知为什么另一道类似的题目依旧超时…)

#include <stdio.h>

int d[1002][1002];
int f[1002][1002];
int kn[1002][1002];
int kt;

int main(){
int n,s[1002],m,t,i,j,k;
while(scanf("%d %d",&n,&m)==2){
s[0]=0;
for (i=1;i<=m;i++)scanf("%d",&s[i]);
s[m+1]=n;
for (i=0;i<=m;i++)
f[i][i+1]=0;
for (i=0;i<=m-1;i++){
f[i][i+2]=s[i+2]-s[i];
kn[i][i+2]=i+1;
}
for (i=3;i<=m+1;i++)
for (j=0;j<=m+1-i;j++){
kt=kn[j][i+j-1]; 
t=f[j][kt]+f[kt][i+j];
for (k=kn[j][i+j-1];k<=kn[j+1][i+j];k++)//这里的区间不重合
if(f[j][k]+f[k][i+j]<t){
t=f[j][k]+f[k][i+j];
kt=k;
}
kn[j][i+j]=kt; //题目关键,记录决策点
f[j][i+j]=t+s[i+j]-s[j];
}
printf("%d\n",f[0][m+1]);
}
return 0;
}

 

转载于:https://www.cnblogs.com/shellbase/archive/2013/03/30/2990660.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值