1. 程式人生 > >【枚舉算法Day1】20170529-2枚舉算法專題練習 題解

【枚舉算法Day1】20170529-2枚舉算法專題練習 題解

沒有 record ole var 如果 ble 但是 ont nbsp

1.OneMoreRectangle 一個矩形

●如果任意枚舉矩形坐標,顯然不可行。數組太大,開不下!
●我們註意到,如果我們放入了矩形,矩形周圍並沒有其它矩形,那麽稍微移動這個矩形,不會改變答案。
顯然,一定存在一種方案,使得放入的矩形的邊界與某些已知矩形邊界重合。
我們不妨規定,放入的矩形下邊界必須與已知矩形重合、左邊界必須與已知矩形重合。

所以就可以做了

 1 type rec=record
 2 x1,y1,x2,y2:longint;
 3 end;
 4 var n,x,y,i,j,k,ans,max,xx,yy:longint;
 5     a:array[1..10000]of rec;
6 begin 7 assign(input,rectangle.in); 8 assign(output,rectangle.out); 9 reset(input); 10 rewrite(output); 11 readln(n,x,y); 12 for i:=1 to n do 13 readln(a[i].x1,a[i].y1,a[i].x2,a[i].y2); 14 for i:=1 to n do 15 for j:=1 to n do begin 16 xx:=a[i].x1; yy:=a[j].y1; 17 ans:=0; 18 for k:=1
to n do 19 if (a[k].x1>=xx)and(a[k].x1<=xx+x)and(a[k].y1>=yy)and(a[k].y2<=yy+y) 20 and(a[k].x2>=xx)and(a[k].x2<=xx+x)and(a[k].y2>=yy)and(a[k].y2<=yy+y)
//這裏是判斷以第i個矩形的左下角坐
標X1,第j個矩形的左下角縱坐標Y1圍成的X*Y的矩形能不能覆蓋第k個矩形
21 then inc(ans);
22 if ans>max then max:=ans;
23 end;
24 writeln(max);
25 close(input);
26 close(output);
27 end.

2.Palindromes回文

對於目前已經實現的算法的平均時間復雜度為O(length(s)*k/2)或許更少,

但是實在想不出辦法來優化,於是就這樣放在這裏吧!

 1 var k,i,ans:longint;
 2     s:ansistring;
 3 function check(l,r:longint):boolean;//判斷字符串s從l位到r位是否為回文
 4 var th:ansistring;
 5     i:longint;
 6 begin
 7  th:=‘‘;
 8  for i:=l to r do th:=th+s[i];
 9  for i:=1 to length(th)div 2+1 do
10   if th[i]<>th[length(th)-i+1] then exit(false);
11  exit(true);
12 end;
13 begin
14 assign(input,palin.in);
15 assign(output,palin.out);
16 reset(input);
17 rewrite(output);
18  readln(k);
19  readln(s);
20  for i:=1 to length(s) do begin
21   if i+k-1>length(s) then break;
22   if check(i,i+k-1) then inc(ans);
23  end;//枚舉當前點和後面連這個點加起來為k位是否為回文
24  writeln(ans); 
25 close(input);
26 close(output);
27 end.

3.ProblemSetter(問題的設置)

一開始想的復雜,選排快排一起用太復雜了點。暴力好像拿了92分!

現在講一種很簡單的辦法!

排序+枚舉(排序:按照簡單-中等-困難的順序輸出)
解決方法是:先從小到大枚舉E,再從大到小枚舉H,最後從小到大枚舉M,取每個值第一個遇到的解。(註意枚舉不重復)
“你希望難度差盡量接近”定義一個函數F(x,y,z:longint):longint;

function F(x,y,z:longint):longint;
begin
exit(abs((a[y]-[x])-(a[z]-a[y])));
end;

接下來是程序:

 1 var n,i,j,e,m,h,k:longint;
 2     a:array[1..50]of longint;
 3 procedure swap(var a,b:longint);
 4 var t:longint;
 5 begin
 6  t:=a; a:=b; b:=t;
 7 end;
 8 function f(x,y,z:longint):longint;
 9 begin
10  exit(abs(abs(a[y]-a[x])-abs(a[z]-a[y])));
11 end;
12 begin
13 assign(input,problemsetter.in);
14 assign(output,problemsetter.out);
15 reset(input);
16 rewrite(output);
17  readln(n);
18  for i:=1 to n do read(a[i]);
19  for i:=1 to n-1 do
20   for j:=i+1 to n do
21    if a[i]>a[j] then swap(a[i],a[j]);
22  E:=1; M:=2; H:=n;//這是所有組合中f最大的!
23  for i:=1 to n do //任意
24   for k:=n downto i+2 do //從最後向前推,註意第i位是E的,第i+1位是M的,所以只能到i+2
25    for j:=i+1 to k-1 do //從E到H(不包含E和H)都可以選
26      if f(i,j,k)<f(E,M,H) then begin
27         E:=i;M:=j;H:=k;//叠代
28      end;
29  writeln(a[E], ,a[M], ,a[H]);//輸出
30  close(input);
31  close(output);
32 end.

4.ColoringRectangles著色的矩形

這道題需要遵循以下步驟

提供以下樣例:

輸入:

3 2
1 3 2
1 2 5
5 7 9
3 4 7

輸出:

2

技術分享

(1)遞歸求出每一個矩形被覆蓋後能看到的面積(註意從後往前枚舉,後保存當前編號ans[i])。
定義一個過程:

procedure cal(l,r,b,t,z:longint); //z為從上到下的該層編號(看下還有多少可能的其他編號的矩形在上面)。
begin
while (z<=n) and ((r<=x1[z]) or (l>=x2[z]) or (t<=y1[z]) or (b>=y2[z])) do inc(z);//一些不符合條件的矩形
if z>n then begin inc(area[now],(r-l)*(t-b));exit;end; //求出area
if l<x1[z] then begin cal(l,x1[z],b,t,z+1);l:=x1[z];end;
if r>x2[z] then begin cal(x2[z],r,b,t,z+1);r:=x2[z];end;
if b<y1[z] then cal(l,r,b,y1[z],z+1);
if t>y2[z] then cal(l,r,y2[z],t,z+1);//分割成四塊來求
end;


(2)按面積area從大到小,相同面積按編號從小到大編號排序

for i:=1 to n-1 do
  for j:=i+1 to n do
  if (area[i]<area[j])or((area[i]=area[j])and(ans[i]>ans[j]))
  then begin swap(area[i],area[j]); swap(ans[i],ans[j]); end;

(3)再按編號從小到大對k個編號ans[]排序,這樣可以按字典序輸出。

 for i:=1 to k-1 do
  for j:=i+1 to k do
   if ans[i]>ans[j] then swap(ans[i],ans[j]);

完整的程序:

 1 var x1,y1,x2,y2,area,ans:array[1..50]of longint;
 2     n,k,now,i,j:longint;
 3 procedure swap(var a,b:longint);
 4 var t:longint;
 5 begin
 6 t:=a; a:=b; b:=t;
 7 end;
 8 procedure cal(l,r,b,t,z:longint);
 9 begin
10   while (z<=n) and ((r<=x1[z]) or (l>=x2[z]) or (t<=y1[z]) or (b>=y2[z])) do inc(z);
11   if z>n then begin inc(area[now],(r-l)*(t-b));exit;end;
12   if l<x1[z] then begin cal(l,x1[z],b,t,z+1);l:=x1[z];end;
13   if r>x2[z] then begin cal(x2[z],r,b,t,z+1);r:=x2[z];end;
14   if b<y1[z] then cal(l,r,b,y1[z],z+1);
15   if t>y2[z] then cal(l,r,y2[z],t,z+1);
16 end;
17 begin
18 assign(input,rectangles.in);
19 assign(output,rectangles.out);
20 reset(input);
21 rewrite(output);
22  readln(n,k);
23  for i:=1 to n do read(x1[i]); readln;
24  for i:=1 to n do read(y1[i]); readln;
25  for i:=1 to n do read(x2[i]); readln;
26  for i:=1 to n do read(y2[i]); readln;
27  for i:=n downto 1 do begin
28   ans[i]:=i;
29   now:=i;
30   cal(x1[now],x2[now],y1[now],y2[now],i+1);
31  end;
32  for i:=1 to n-1 do
33   for j:=i+1 to n do
34   if (area[i]<area[j])or((area[i]=area[j])and(ans[i]>ans[j]))
35   then begin swap(area[i],area[j]); swap(ans[i],ans[j]); end;
36  for i:=1 to k-1 do
37   for j:=i+1 to k do
38    if ans[i]>ans[j] then swap(ans[i],ans[j]);
39   for i:=1 to k-1 do write(ans[i]-1, );
40   writeln(ans[k]-1);
41   close(input);
42   close(output);
43 end.

【枚舉算法Day1】20170529-2枚舉算法專題練習 題解