这套题真有点搞笑....但是难度真的不错!学到了不少新的思想。同样,又被虐了一次..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 |
题解:
一题,说实话就是爆搜!我开始的时候还去剪枝,结果弄的挂掉了。
倒霉啊...
没有技术含量...怪不得是第一题....被雷焦了....
代码如下:
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<>i 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:=b 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>n then
68 begin
69 if u=(1 shl n)-1 then
70 begin
71 z1:=0;
72 for i:=n 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)。我的程序比较慢
注意:不要忽略两点之间有多条边的情况……
总的来说,就是搜索加剪枝....嗯....我多想了.....
代码如下:
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]<>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))<>0) then
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>r then exit;
76 if k>m then
77 begin
78 if u=0 then exit;
79 if t<r 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!