一、动态规划(3)递增序列
来源:互联网 发布:淘宝推广软件有用吗 编辑:程序博客网 时间:2024/06/14 21:49
源程序名 INCSQ.??? (PAS, C, CPP)
可执行文件名 INCSQ.EXE
输入文件名 INCSQ. IN
输出文件名 INCSQ. OUT
给定一个数字串,请你插入若干个逗号,使得该数字串成为一个严格递增的数列且最后一个数要尽可能小,在这个问题中,前导的零是允许出现在数的前面的。
输入输入数据仅含一行,为一个长度不超过 80 的数字串。
输出
输出一个严格递增且最后一数最小的数列,相邻两个数之间用一个逗号隔开,如果有多
个数列满足要求,则输出第一个数最大的那个数列,若这样的解还不止一个,则输出第二个数最大的那个数列,以此类推。
样例INCSQ. IN
100000101
INCSQ. OUT
100,000101
分析:
设f[i,j]表示前i个字符划分成为j个部分,最后一个数字为最小值时最后数字的开头字母序号。比如100000101这个状态,f[9,1]=1,f[9,2]=4,就是说样例中的第四个数字‘0’是第二个数字的开头。
f[i,j]=max{k | 数字f[k-1,j-1]到k-1串的值小于k到i的串的值,即这种划分满足后面一个数大于这个数前面划分所得末尾最小值 且 f[k-1,j-1]是一种成立的划分}
然后就是处理边界,细节见程序。
上面说到了如何保证末尾最小,但是如何保证开头最大,我为此WA了两次。很简单,在末尾数相同的情况下,划分的数量也就是添加的逗号越少,相应开头数就越大。在所有f[len,j]的情况中,开头永远都是以末尾最小为前提的。
然后根据方程记录的结果倒推。
这道题灵活运用了动归的重要思想:无后效性。f[i,j]表示划分的断点位置,而不是划分出来的最后一个数的值,f[i,j]既表示了前i个数字划分成j个部分时,后面数字的最小值,又表示了这种状态。我们可以根据f[i,j]的值推知 f[f[i,j]-1,j-1]。这里的问题在于:第1个到f[i,j]-1,第f[i,j]个到i个,两个字串是独立的,前面的处理让第1个到f[i,j]-1的末尾数最小了,为后面提供成立的可能。
代码:
var
a:string;
f:array[0..80,0..80]of longint;
len,i,j,k,last:longint;
flag:boolean;
function compare(i,j,x,y:longint):boolean;
var
k:longint;
begin
while (a[i]='0') and (i<j) do inc(i);
while (a[x]='0') and (x<y) do inc(x);
if j-i<y-x then exit(true);
if j-i>y-x then exit(false);
for k:=0 to j-i do
begin
if a[i+k]<a[x+k] then exit(true);
if a[i+k]>a[x+k] then exit(false);
end;
exit(false);
end;
procedure print(x,y:longint);
var
i:longint;
begin
if y=1 then
begin
for i:=1 to x do
write(a[i]);
if x<len then write(',');
exit;
end;
print(f[x,y]-1,y-1);
for i:=f[x,y] to x do
write(a[i]);
if x<len then write(',');
end;
begin
assign(input,'incsq.in');
assign(output,'incsq.out');
reset(input);
rewrite(output);
readln(a);
len:=length(a);
last:=1;
fillchar(f,sizeof(f),0);
for i:=0 to len do f[i,1]:=1;
for i:=2 to len do
for j:=2 to i do
begin
flag:=false;
for k:=j to i do
if (f[k-1,j-1]<>-1) and compare(f[k-1,j-1],k-1,k,i) then
begin
f[i,j]:=k;
flag:=true;
end;
if flag then last:=j else f[i,j]:=-1;
end;
for i:=len downto 1 do
if f[len,last]<=f[len,i] then last:=i;
print(len,last);
writeln;
close(input);
close(output);
end.
- 一、动态规划(3)递增序列
- 最长递增子序列(动态规划)
- 最长递增子序列(动态规划)
- 最长递增子序列(动态规划)
- 动态规划题目一:最长单调递增子序列
- 动态规划实例(一):最长递增子序列(LIS)
- 【动态规划】最长递增子序列代码(UVA 10131)
- 最长递增子序列LIS(动态规划+二分查找)
- 动态规划-单调递增最长子序列(三)
- [动态规划] 最长递增子序列 (Longest Increasing Subsequence)
- ny17单调递增最长子序列(动态规划)
- 单调递增最长子序列 (动态规划经典题)
- 动态规划(最长相同子序列,递增)
- 动态规划求最长递增子序列(BJFUOJ 1482)
- 单调递增最长子序列(动态规划)
- 51nod--1134 最长递增子序列 (动态规划)
- 动态规划 —— 最长递增子序列(LIS)
- 动态规划之-----单调递增最长子序列(nyoj17)
- remove-duplicates-from-sorted-array-ii
- TCP长连接与短连接的区别
- android 轮播图手动循环滑动+自动循环滑动
- ios修改NavigationController的背景颜色
- 欢迎使用CSDN-markdown编辑器
- 一、动态规划(3)递增序列
- Hello world!
- 您的服务器设置了 open_base_dir 下安装ECshop后后台提示: 您的服务器设置了 open_base_dir 且没有包含 C:\WINDOWS\Temp,您将无法上传文件。 解决方法
- Eclipse当中的Copy Qualified Name
- 升级Xcode 导致插件失效的解决办法
- Spring 注解@Transactional
- POJ2914
- #19 Remove Nth Node From End of List
- HDU-1052-Tian Ji -- The Horse Racing(C++ && 简单贪心)