您的位置:首页 > 其它

2016.08.17【初中部 NOIP提高组 】模拟赛C

2016-08-17 11:25 357 查看
第一题:

https://61.142.113.109/senior/#main/show/3076

题目描述:

【备战NOIP2012图论专项模拟试题】位图 (Standard IO)

给出一个大小为n行*m列的矩形位图。该位图的每一个象素点不是白色就是黑色,但是至少有一个象素点是白色。在i行j列的象素点我们称为点(i,j)。两个象素点p1=(i1,j1)和p2=(i2,j2)之间的距离定义如下:

d(p1,p2)=|i1-i2|+|j1-j2|

现在的任务是:对于每一个象素点,计算它到最近的白色点的距离。如果它本身是白色点,距离为0。

Input

【输入格式】

第1行:2个整数n,m(1<=n <=182,1<=m<=182)

接下来n行,每一行有一个长度为m的0/1字符串,描述一行象素点。如果点(i,j)为白色,则值为1,否则值为0。

Output

【输出格式】

共n行,每行有m个整数,数之间用1个空格分开,分别表示对应的象素点距离白色点的距离。

Sample Input

3 4

0001

0011

0110

Sample Output

3 2 1 0

2 1 0 0

1 0 0 1

很水的一道题,

和以前做的https://61.142.113.109/senior/#main/show/1445这题很像

首先把所有白点存进队列里,

对于队列里每个数,把它上下左右赋值为它的值+1,

如果它上下左右已经有值就不用再往下赋值了,

就这样宽搜以此类推

参考程序:

var     n,m,i,j,k,x,y:longint;
a:array[0..200,0..200]of char;
f,bz:array[0..200,0..200]of longint;
b:array[0..40000,1..2]of longint;
data:array[1..100000,1..3]of longint;
f1:array[1..4]of longint=(-1,0,1,0);
f2:array[1..4]of longint=(0,1,0,-1);
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(a[i,j]);
if a[i,j]='1' then
begin
inc(b[0,1]);
b[b[0,1],1]:=i;
b[b[0,1],2]:=j;
end;
end;
readln;
end;
for i:=1 to b[0,1] do
begin
data[i,1]:=b[i,1];
data[i,2]:=b[i,2];
bz[b[i,1],b[i,2]]:=1;
end;
i:=0;
j:=b[0,1];
while i<j do
begin
inc(i);
for k:=1 to 4 do
begin
x:=data[i,1]+f1[k];
y:=data[i,2]+f2[k];
if(x>0)and(x<=n)and(y>0)and(y<=m)and(bz[x,y]=0)then
begin
inc(j);
data[j,1]:=x;
data[j,2]:=y;
data[j,3]:=data[i,3]+1;
f[x,y]:=data[j,3];
bz[x,y]:=1;
end;
end;
end;
for i:=1 to n do
begin
for j:=1 to m do write(f[i,j],' ');
writeln;
end;
end.


第二题:

https://61.142.113.109/senior/#main/show/3077

题目描述:

【备战NOIP2012图论专项模拟试题】外星人入侵 (Standard IO)

外星人入侵地球。可怕的吃人外星人正在全国各地依次序建立它们的基地。

全国共有N(1≤ N ≤10,000)座城市,城市编号1~N。城市之间有M(0≤ M ≤100,000)条双向道路相连。外星人计划建立A(0≤A≤N)个基地。

你只有在距离当前所有外星人基地至少K(1≤K≤100)单位长度的城市才能得到安全。

所以你必须赶快写一个程序决定走到哪里去。

Input

第1行:4个整数N, M, A, K

接下来M行,每行3个整数T1, T2(1≤T1<T2≤N)和D(1≤D≤100),表示城市T1与T2之间有一条长度为D的道路。两个城市之间最多有一条直连道路。

接下来A行,每行1个整数Bi(1≤Bi≤N),表示外星人依次序建的第i个基地所在的城市编号。

Output

共A行,第i行1个整数,表示当外星人建好第i个基地后,距离当前所有基地B1,B2,...,Bi至少K长度的城市的数量。

Sample Input

7 6 3 3

1 2 1

1 3 1

2 5 1

3 6 1

1 4 1

4 7 2

2

1

4

Sample Output

2

1

0

这题我还是用暴力宽搜,

对于一个新建立的基地,枚举它能够到达的城市,

如果能够对这个城市产生威胁,那么这个城市就不能再居住,

之后再往下枚举,以此类推

这里有个优化,就是当前安全城市数为0时,

以后每个时间段的安全城市数一定就是0了,直接输出就好了

参考程序:

var     n,m,a,k,x,y,t,i,j,ans:longint;
f,f2:array[1..10000,0..2000]of 0..10000;
bz:array[1..10000]of longint;
data:array[1..50000,1..2]of longint;
procedure bfs;
var     l,r,i,t:longint;
begin
l:=0;
r:=1;
while l<r do
begin
inc(l);
t:=data[l,1];
for i:=1 to f[t,0] do
begin
if (bz[f[t,i]]>data[l,2]+f2[t,i])
and(data[l,2]+f2[t,i]<k) then
begin
if bz[f[t,i]]=maxlongint then dec(ans);
bz[f[t,i]]:=data[l,2]+f2[t,i];
inc(r);
data[r,1]:=f[t,i];
data[r,2]:=data[l,2]+f2[t,i];
end;
end;
end;
end;
begin
readln(n,m,a,k);
for i:=1 to m do
begin
readln(x,y,t);
inc(f[x,0]);
f[x,f[x,0]]:=y;
inc(f[y,0]);
f[y,f[y,0]]:=x;
f2[x,f[x,0]]:=t;
f2[y,f[y,0]]:=t;
end;
for i:=1 to n do bz[i]:=maxlongint;
ans:=n;
for i:=1 to a do
begin
readln(x);
data[1,1]:=x;
data[1,2]:=0;
if bz[x]=maxlongint then dec(ans);
bz[x]:=0;
bfs;
writeln(ans);
if ans=0 then
begin
for j:=i+1 to a do writeln(0);
break;
end;
end;
end.


第三题:
https://61.142.113.109/senior/#main/show/3078

题目描述:

【备战NOIP2012图论专项模拟试题】无线通讯网 (Standard IO)

国防部计划用无线网络连接若干个边防哨所。2种不同的通讯技术用来搭建无线网络:每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。

任意两个配备了一条卫星电话线路的哨所均可以通话,无论它们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过D,这是受收发器的功率限制。收发器的功率越高,通话距离D会更远,但同时价格也更贵。

收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话说,每一对哨所之间的通话距离都是同一个D。

你的任务是确定收发器必须的最小通话距离D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。

Input

第1行:2个整数S(1 <= S <= 100)和P(S < P <= 500),S表示可安装的卫星电话的线路数,P表示边防哨所的数量。

接下来P行,每行描述一个哨所的平面坐标(x,y),以km为单位,整数,0<=x,y<=10,000

Output

第1行:1个实数D,表示无线电收发器的最小传输距离。精确到小数点后2位。

Sample Input

2 4

0 100

0 300

0 600

150 750

Sample Output

212.13

这题其实可以转化为:

有P个节点,且每个节点都可以到达其它的节点,求第P-S长的边的长度。

这题要用最小生成树算法,

参考程序:



var     n,m,i,j,lenb,t:longint;
b:array[0..500000] of real;
a,c:array[0..250000,0..2] of longint;
f:array[0..500000] of longint;
procedure kuaipai(l,r:longint);
var     i,j:longint;
mid:real;
begin
i:=l;
j:=r;
mid:=b[r];
while i<=j do
begin
while b[i]<mid do inc(i);
while b[j]>mid do dec(j);
if i<=j then
begin
b[0]:=b[i];
b[i]:=b[j];
b[j]:=b[0];
c[0]:=c[i];
c[i]:=c[j];
c[j]:=c[0];
inc(i);
dec(j);
end;
end;
if i<r then kuaipai(i,r);
if l<j then kuaipai(l,j);
end;
function getfather(x:longint):longint;
begin
if f[x]=0 then exit(x);
f[x]:=getfather(f[x]);
exit(f[x]);
end;
begin
readln(m,n);
for i:=1 to n do
readln(a[i,1],a[i,2]);
for i:=1 to n-1 do
for j:=i+1 to n do
begin
inc(lenb);
b[lenb]:=sqrt(sqr(a[i,2]-a[j,2])+sqr(a[i,1]-a[j,1]));
c[lenb,1]:=i;
c[lenb,2]:=j;
end;
kuaipai(1,lenb);
for i:=1 to lenb do
begin
if getfather(c[i,1])<>getfather(c[i,2]) then
begin
f[getfather(c[i,1])]:=getfather(c[i,2]);
inc(t);
if t=n-m then
begin
writeln(b[i]:0:2);
exit;
end;
end;
end;
end.


第四题:

https://61.142.113.109/senior/#main/show/3079

题目描述:

【备战NOIP2012图论专项模拟试题】砍树 (Standard IO)

给出一个树形图("tree-shaped" network),有N(1 <= N <= 10,000)个顶点。如果删除树上某一个顶点,整棵树就会分割成若干个部分。显然,每个部分内部仍保持连通性。

现在问:删除哪个点,使得分割开的每个连通子图中点的数量不超过N/2。如果有很多这样的点,就按升序输出。

例如,如图所示的树形图,砍掉顶点3或者顶点8,分割开的各部件。

Input

第1行:1个整数N,表示顶点数。顶点编号1~N

第2..N行:每行2个整数X和Y,表示顶点X与Y之间有一条边

Output

若干行,每行1个整数,表示一个符合条件的顶点的编号。如果没有顶点符合条件,则仅在第1行上输出"NONE"

Sample Input

10

1 2

2 3

3 4

4 5

6 7

7 8

8 9

9 10

3 8

Sample Output

3

8

我们先从第一个位置进行一次DFS,之后记录下以当前节点为根节点时的子节点数量

之后枚举断开的位置,

当子树的根的父亲是断掉点的儿子或断掉点本身,则直接加上子树根的答案.

记录答案之后直接判断是否<=n div 2并且所有节点数量-这个点的子节点数量<=n div 2就输出

参考程序:

var     a:array[1..10000,0..1000]of longint;
f,bz,bz2:array[1..10000]of longint;
i,j,x,y,n:longint;
procedure dfs(x:longint);
var     i:longint;
begin
bz[x]:=1;
if a[x,0]=0 then
begin
f[x]:=1;
exit;
end;
for i:=1 to a[x,0] do
begin
if bz[a[x,i]]=1 then continue;
dfs(a[x,i]);
f[x]:=f[x]+f[a[x,i]];
if f[a[x,i]]>n div 2 then bz2[x]:=1;
end;
f[x]:=f[x]+1;
if n-f[x]>n div 2 then bz2[x]:=1;
end;
begin
readln(n);
for i:=1 to n-1 do
begin
readln(x,y);
inc(a[x,0]);
a[x,a[x,0]]:=y;
inc(a[y,0]);
a[y,a[y,0]]:=x;
end;
dfs(1);
for i:=1 to n do
if bz2[i]=0 then writeln(i);
end.


我们先从第一个位置进行一次DFS,之后记录下以当前节点为根节点时的节点数量(即把当前节点下的子树的节点数量加起来再加上自己本身)。

之后枚举断开的位置,如果断开之后的图节点大于当前节点的结果,就把它变成(N-节点数)。

再判断有没有超过N div 2,如果超过就继续枚举,没有超过就输出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: