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

来源:互联网 发布:图像算法 编辑:程序博客网 时间:2024/05/10 06:48

第一题:

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,如果超过就继续枚举,没有超过就输出。


3 0
原创粉丝点击