添括號問題(NOI 96)

2021-05-25 21:06:54 字數 3103 閱讀 9017

一、試題

有乙個由數字1,2,... ,9組成的數字串(長度不超過200),問如何將m(m<=20)個加號("+")插入到這個數字串中,使所形成的算術表示式的值最小。請編乙個程式解決這個問題。

注意:加號不能加在數字串的最前面或最末尾,也不應有兩個或兩個以上的加號相鄰。

m保證小於數字串的長度。

例如:數字串

79846

,若需要加入兩個加號,則最佳方案為

79+8+46

,算術表示式的值

133。

[輸入格式]

從鍵盤讀入輸入檔名。數字串在輸入檔案的第一行行首(數字串中間無空格且不折行),m的值在輸入檔案的第二行行首。

[輸出格式]

在螢幕上輸出所求得的最小和的精確值。

輸入示例

82363983742

3輸出示例

2170

二、分析

這道題目是經典的動態規劃的題目

.因此肯定採用動態規劃.

考慮到資料的規模超過了長整型

,我們注意在解題過程中採用高精度演算法.

規劃方程

:f[i,j] = min (i-1<=k<=j-1)

邊界值:f[0,i] := num[1,i];

f[i,j]

表示前j

個數字中添上

i個加號後得到的最小值。

num[i,j]

表示數字串第

i位到第

j位的數

程式需要的空間約為

20 * 200 * 200.

顯然難以承受。

但是,還能更優。每一步,我們都只與上一步有關。因此可以採用滾動陣列,這樣,複雜度就降到了

2 * 200 * 200

左右了。

程式的時間效率約為

20 * 200 * 200.

時間上根本不成問題。

這道題目看起來很容易

,但是如果在程式設計時不多加細心,容易的問題也難免會有這樣那樣的錯誤。因此

,越是簡單的題目越要細心,不能粗枝大葉。

三、參考程式

program noi96_4;

const

filein='input.txt';

fileou='output.txt';

type

stype=string[202];

varf1 , f2:array[1..200] of ^stype;

st:string;

fi,fo:text;

n , m:integer;

procedure init;

vari , j , k : integer;

begin

assign(fi,filein);

assign(fo,fileou);

reset(fi);

rewrite(fo);

readln(fi,st);

n := length(st);

readln(fi,m);

close(fi);

for i := 1 to 200 do

begin new(f1[i]);fillchar(f1[i]^,sizeof(f1[i]^),'0');end;

for i := 1 to 200 do

begin new(f2[i]);fillchar(f1[i]^,sizeof(f1[i]^),'0');end;

for i := 1 to n do

f1[i]^ := copy(st,1,i);

end;

function big(st1,st2:string):boolean;

begin

big := ( length(st1)>length(st2) ) or

( length(st1)=length(st2) ) and ( st1 > st2 );

end;

procedure sum(st1,st2:string;var st3:string);

vari , j , k, l , o , p : integer;

begin

st3 := '';

while length(st1)

while length(st2)

p := 0;

for o := length(st1) downto 1 do

begin

val(st1[o],i,l);

val(st2[o],j,l);

k := (i+j+p) mod 10;

p := (i+j+p) div 10;

st3 := chr(k+48) + st3;

end;

if p>0 then st3 := chr(p+48) + st3;

while (st3[1]='0') and (length(st3)>1) do delete(st3,1,1);

end;

procedure dynamic;

vari, j , k , l , o , p: integer;

st1 , st2 , st3: string;

begin

for i := 1 to m do

begin

for j := 1 to 200 do

fillchar(f2[j]^,sizeof(f2[j]^),'0');

for j := i+1 to n-m+i do

for k := i to j-1 do

if (k >= i) and ( k < j ) and(j-k<=101) then

begin

sum(f1[k]^,copy(st,k+1,j-k),st3);

if big(f2[j]^,st3) or (f2[j]^='0') then

f2[j]^ := st3;

end;

for j := 1 to 200 do

f1[j]^ := f2[j]^;

end;

end;

begin

init;

dynamic;

writeln(fo,f1[n]^);

close(fo);

end.

添柴 12014 括號匹配 解題報告

題目描述 id 12014 括號匹配 標籤 資料結構 棧詳情 在程式設計當中我們只會用到三種括號 圓括號 方括號和花括號 編譯器在編譯的時候會檢查括號是否正確匹配。例如 都是合法的匹配。但是 則是不合法的匹配。請編寫乙個程式來判斷輸入的括號序列是否合法。輸入格式 只有一行,為 組成的序列,長度不超過...

leetcode 921 使括號有效的最少新增 棧

描述 給定乙個由 和 括號組成的字串 s,我們需要新增最少的括號 或是 可以在任何位置 以使得到的括號字串有效。從形式上講,只有滿足下面幾點之一,括號字串才是有效的 它是乙個空字串,或者 它可以被寫成 ab a 與 b 連線 其中 a 和 b 都是有效字串,或者 它可以被寫作 a 其中 a 是有效字...

LeetCode921 使括號有效的最少新增

給定乙個由 和 括號組成的字串 s,我們需要新增最少的括號 或是 可以在任何位置 以使得到的括號字串有效。從形式上講,只有滿足下面幾點之一,括號字串才是有效的 它是乙個空字串,或者 它可以被寫成 ab a 與 b 連線 其中 a 和 b 都是有效字串,或者 它可以被寫作 a 其中 a 是有效字串。給...