TSOI2006_3题目解析

这套题真有点搞笑....但是难度真的不错!学到了不少新的思想。同样,又被虐了一次..ToT

 

NOIP第九次模拟试题

 

第一题: How Big Is It? (howbig.pas/.c/.cpp)

 

x要搬家,他要把他的东西打包,包括他收集的一些circles。给n个圆,你要写一个程序找到一个最小的长方形的盒子,使这个盒子能够装下这n个圆,所有的圆必须紧挨着盒子的下边界(见下图)。

 

Input (howbig.in)

一个整数n (n<=8),后面n个实数,表示n个圆的半径。

Output (howbig.out)

一个实数,表示盒子的最小长度,保留3位小数。

 

Sample

Input

Output

3 2.0 1.0 2.0

9.657

 

 

 第二题: Pairsumonious Numbers (pairsu.pas/.c/.cpp)

 

如果有N个整数,我们可以通过把它们两两相加得到N*(N-1)/2个和。现在给出这N*(N-1)/2个和,求这N个整数。

 

Input (pairsu.in)

一个整数N (2<N<10),后面N*(N-1)/2个整数,表示那N*(N-1)/2组和。

Output (pairsu.out)

如果有解,在一行上从小到大输出得到的N个数。否则,输出”Impossible”

输入数据保证最多有一组解。

 

Sample

Input

Output

3 1269 1160 1663

383 777 886

3 1 1 1

Impossible

 

 

第三题: Reliable Nets (reliab.pas/.c/.cpp)

 

某学校正在建设新校区,由信息学小组负责规划校园网。

新校区有n栋楼,因地形关系,只有m对楼之间可以用光纤直接连接,并且连接两栋楼有一个花费值。

为了保证网络能够安全地工作,要把网络建成”Reliable Net”,即如果任意一条光纤出现问题,剩下网络还是连通的(n栋楼是连通)。

请你编程求出建立一个”Reliable Net”的最小花费。

 

Input (reliab.in)

第一行两个正整数n,m (2<=n<=15, m<=20)

下面有m行,每行三个整数a b c ,表示a楼和b楼是可以直接连接的,并且连接它们的花费是c

两栋楼之间可能有多条可行线路。

Output (reliab.out)

如果能建成”Reliable Net”,输出 “The minimal cost is <cost>.” <cost>为最小的花费,否则输出 ”There is no reliable net possible.”

 

Sample

Input

Output

4 5

1 2 1

1 3 2

2 4 2

3 4 1

2 3 1

The minimal cost is 6.

2 1

1 2 5

There is no reliable net possible.

 

 

第四题: Instructions (instru.pas/.c/.cpp)

 

Mark I 是某学校附属矿业公司为勘测矿藏设计的第一代机器人。

要勘测的土地被分成若干格子,每个格子下面有矿或者没有矿……机器人的任务就是勘测这块土地下面的矿藏。

Mark I可以执行下面四种指令:

Forward : 机器人向前走一格;

Turn Left : 机器人向左转;

Turn Right : 机器人向右转;

Scan : 机器人探测它前面一格的矿储藏情况。(并不向前走)

Mark I 太实用了,它给公司带来了巨大的收益。但是与此同时,其它公司也开始设计类似的产品。为了保持对市场的占有,公司推出了Mark II —— 第二代勘矿机器人。考虑到有客户抱怨上一代机器人使用起来比较复杂,Mark II 不再使用以前的指令集,而是只使用两种指令—— Move & Scan

Move的使用方法:

   Move DIR N : DIR代表方向,可以是”Forward””Back””Left””Right”N是一个

正整数。机器人会先转到相应的方向,然后向前走N格。

Scan 的使用方法:

Scan DIR : DIR同样代表方向,可以是”Forward””Back””Left””Right”。机器人会转到相应的方向,然后探测它前面的格子。

为了说服 Mark I 的老客户为他们的机器人升级,公司决定为 Mark II 安装一个新的芯片,使 Mark II 具有把老式指令转换成新式指令的功能。

 

Input (instru.in)

第一行有一个正整数n (n<=1000),表示下面有n条老式指令。

以下n行,每行一条老式指令。

Output (instru.out)

输出最少需要多少条新式指令能够达到与输入的老式指令等效。

等效意味着:如果开始时在相同的格子,面向相同的方向,那么机器人会按照相同的顺序探测相同的格子。

 

Sample

Input

Output

8

Forward

Forward

Turn Left

Forward

Scan

Turn Right

Scan

Forward

4

 

题解:

一题,说实话就是爆搜!我开始的时候还去剪枝,结果弄的挂掉了。

倒霉啊...

没有技术含量...怪不得是第一题....被雷焦了....

代码如下:

 

  1 var
  2         n,i:longint;r,big:real;
  3         a,site:array[0..8]of real;
  4         p:array[0..8]of longint;
  5 procedure sort;
  6 var
  7         i,j,g:longint;t:real;
  8 begin
  9         for i:=1 to n-1 do
 10           begin
 11                 g:=i;
 12                 for j:=i+1 to n do
 13                         if a[g]<a[j] then g:=j;
 14                 if g<>then
 15                         begin
 16                                 t:=a[g];a[g]:=a[i];a[i]:=t;
 17                         end;
 18           end;
 19 end;
 20 procedure init;
 21 var
 22         i,j,k:longint;z1,z2:real;
 23 begin
 24 //        n:=8;
 25         read(n);
 26         for i:=1 to n do read(a[i]);
 27 //        sort;
 28         site[1]:=a[1];
 29         k:=1;
 30         for i:=2 to n do
 31                 begin
 32                         z1:=0;
 33                         for j:=i-1 downto 1 do
 34                             begin
 35                                  z2:=site[j]+sqrt(4*a[i]*a[j]);
 36                                  if z2>z1 then z1:=z2;
 37                             end;
 38                         site[i]:=z1;
 39                         if site[i]<a[i] then site[i]:=a[i];
 40                 end;
 41         z1:=0;
 42         for i:=1 to n do
 43             begin
 44                  z2:=site[i]+a[i];
 45                  if z2>z1 then z1:=z2;
 46             end;
 47         r:=z1;
 48 end;
 49 function get(k,b:longint):real;
 50 var
 51    i,j:longint;z1,z2:real;
 52 begin
 53      z1:=0;
 54      for i:=downto 1 do
 55          begin
 56               z2:=site[i]+sqrt(4*a[k]*a[p[i]]);
 57               if z2>z1 then z1:=z2;
 58          end;
 59      if z1<a[k] then z1:=a[k];
 60      get:=z1;
 61 end;
 62 procedure find(m,u:longint);
 63 var
 64         i,z:longint;z1,z2,t1,t2:real;
 65 begin
 66         if (site[m-1]+a[p[m-1]]>=r) then exit;
 67         if m>then
 68                 begin
 69                         if u=(1 shl n)-1 then
 70                                 begin
 71                                         z1:=0;
 72                                         for i:=downto 1 do
 73                                             begin
 74                                                  z2:=site[i]+a[p[i]];
 75                                                  if z2>z1 then z1:=z2;
 76                                             end;
 77                                         if r>z1 then r:=z1;
 78                                 end;
 79                         exit;
 80                 end;
 81         z:=1;
 82         for i:=1 to n do
 83                 begin
 84                         if (z and u)=0 then
 85                                 begin
 86                                         p[m]:=i;
 87                                         site[m]:=get(i,m-1);
 88                                         find(m+1,u or z);
 89                                 end;
 90                         z:=z shl 1;
 91                 end;
 92 end;
 93 begin
 94         assign(input,'howbig.in');reset(input);
 95         assign(output,'howbig.out');rewrite(output);
 96         init;
 97         for i:=1 to n do
 98                 begin
 99                         p[1]:=i;
100                         site[1]:=a[i];
101                         find(2,1 shl (i-1));
102                 end;
103         if r<big then r:=big;
104         writeln(r:0:3);
105         close(input);close(output);
106 end.

 

题2,咱数学丑...跳过先

题3.....怎么说呢....又被雷了....怎么又是搜索啊....

开始我还以为是最小生成树加贪心....当然结果是挂掉...

直接调大牛的题解:

Problem 3: Reliable Nets
题目来源:East Central North America 2005
2^m枚举所有边是否出现。
用并查集判断得到的图是否连通。
如果连通,再判断拆掉一条边之后是否连通。如全都连通,则为一组可行解。
如何快速判断拆掉一条边的新图是否连通呢?由于图总共有2^m种,把边的情况用二进制表示,用一个2^m的数组记录每种图的连通情况,就可以对于同一种图不做重复计算。
总的复杂度为O((n+m)*2^m)。我的程序比较慢􀀯
注意:不要忽略两点之间有多条边的情况……

总的来说,就是搜索加剪枝....嗯....我多想了.....

代码如下:

 

  1 type
  2         edge=record
  3                 x,y,l:longint;
  4         end;
  5 var
  6         n,all,m,r:longint;
  7         bian:array[0..20]of edge;
  8         group:array[0..20]of longint;
  9         used:array[0..20]of boolean;
 10         v,ok:array[0..1 shl 20]of boolean;
 11 function get(m:longint):longint;
 12 begin
 13         if group[m]<>then group[m]:=get(group[m]);
 14         exit(group[m]);
 15 end;
 16 function prep(u:longint):boolean;
 17 var
 18    i,j,h1,h2,t,z:longint;
 19 begin
 20      for i:=1 to m do if u and (1 shl(i-1))<>0 then
 21          begin
 22               z:=u xor (1 shl(i-1));
 23               if not(v[z]) then
 24               begin
 25                    for j:=1 to n do group[j]:=j;
 26                    for j:=1 to m do if (z and(1 shl (j-1))<>0then
 27                    with bian[j] do
 28                         begin
 29                              h1:=get(x);h2:=get(y);
 30                              if h1<>h2 then group[h1]:=h2;
 31                         end;
 32                    t:=get(1);
 33                    ok[z]:=true;
 34                    for j:=2 to n do
 35                    begin
 36                         if t<>get(j) then
 37                            begin
 38                                 ok[z]:=false;
 39                                 break;
 40                            end;
 41                    end;
 42                    v[z]:=true;
 43               end;
 44               if not(ok[z]) then exit(false);
 45          end;
 46      exit(true);
 47 end;
 48 procedure init;
 49 var
 50         i:longint;
 51 begin
 52         assign(input,'reliab.in');reset(input);
 53         fillchar(v,sizeof(v),0);
 54         fillchar(ok,sizeof(ok),0);
 55         readln(n,m);
 56         all:=0;
 57         for i:=1 to m do with bian[i] do
 58                 begin
 59                         readln(x,y,l);
 60                         all:=all+l;
 61                 end;
 62         close(input);
 63         if not(prep((1 shl m)-1)) then
 64            begin
 65                 assign(output,'reliab.out');rewrite(output);
 66                 writeln('There is no reliable net possible.');
 67                 close(output);
 68                 halt;
 69            end;
 70 end;
 71 procedure scan(k,u,t:longint);
 72 var
 73    i,z:longint;
 74 begin
 75      if t>then exit;
 76      if k>then
 77         begin
 78              if u=0 then exit;
 79              if t<then
 80                 begin
 81                      if prep(u) then r:=t;
 82                 end;
 83              exit;
 84         end;
 85      scan(k+1,u,t);
 86      scan(k+1,u or (1 shl (k-1)),t+bian[k].l);
 87 end;
 88 procedure find;
 89 var
 90         z,i,j,h1,k,h2,t:longint;ok:boolean;
 91 begin
 92         r:=all;
 93         scan(1,0,0);
 94         assign(output,'reliab.out');rewrite(output);
 95         writeln('The minimal cost is ',r,'.');
 96         close(output);
 97 end;
 98 begin
 99         init;
100         find;
101 end.

 

题4...真的一道很没意思的题....我又多想了...

开始题都米看懂....一直不理解那个答案怎么得出的....结果大牛的题解说:题目中不是说了吗?叫你实现相同的探索!拜托!是探索,谁叫你这么傻X要去把所有步骤都模拟啊!傻X。。。。。

于是我迷茫了...到底是题我把傻X了还是我把题傻X了....

如果上天再让我做一次这套题,我要用最SB的方法去AC!

posted @ 2009-11-06 11:06  瀑布飞鹰  阅读(210)  评论(0编辑  收藏  举报