莞中松山湖长沙一中三校联考试题.docx
《莞中松山湖长沙一中三校联考试题.docx》由会员分享,可在线阅读,更多相关《莞中松山湖长沙一中三校联考试题.docx(12页珍藏版)》请在冰豆网上搜索。
莞中松山湖长沙一中三校联考试题
莞中-松山湖-长沙一中三校联考试题
SubRaY被布置了n道作业题,可是他一道也不会..但他知道有w位高手,并知道每位高手会做哪些题,请问SubRaY至少请多少位高手,才能把所有的题都做出来?
[输入][solve.in]
第一行两个整数n,w表示有n道作业题和w位高手,作业题以1..n编号.接下来w行,第i+1行第一个数li表示第i位高手会做的题目的数量,接下来li个数表示第i位高手会做哪些题目.
[输出][solve.out]一个数,SubRaY至少要请多少位高手.
[样例输入]
44
212
14
3234
213
[样例输出]
2
[数据范围]
对于40%的数据,3<=n,w<=10,
对于100%的数据,3<=n,w<=60,1<=li<=6
解法:
搜索题,本来打算n只开到10作为一道送分题的(这也是为什么这道题是第一题的原因),但是鉴于如果真这么做实在太水(掉RP),所以改为设4个送分点….
搜索是基础算法.虽然近几年中NOIP搜索题占的比率并不大,但是在考试临近结束时,或者有题不会时,写一个简单的搜索程序往往会带来意想不到的结果.比如2006年的金明的预算方案,有很多大牛虽然写了DP但是某一个小细节处理错了,0分;那些写搜索的反而至少能得40-50分,加几条剪枝甚至能达到80-90分.可见搜索在实战中的作用.
这道题并不难,只需加几条剪枝就可全过:
1可行性剪枝,如果当前选择的高手的数量已经大于等于当前最优解的数量,剪.这也是最基础,最简单,但却是最实用的剪枝之一.
2重复数据数据中不可避免地会出现某一个高手会做的题目,有另外一个高手全会做的情况.这种情况下,这个高手就不需要了,因为它完全可以被另外那个高手取代.
3仅有情况有的题只能被一位高手解决,所以在搜索之前把这位高手会做的题目删去吧,最优解中一定包含这位高手,所以这些题一定能被解决.
其实这道题模型就是2011年东莞特长生考试最后一题。
程序:
vari,j,k,n,m,ans,max,x:
longint;
a:
array[1..60,1..6]oflongint;
b:
array[1..60,1..60]ofboolean;
l,d:
array[1..61]oflongint;
s:
array[1..60,0..60]oflongint;
can:
boolean;
proceduredfs(v,x:
longint);
vari,j,k:
longint;
begin
while(d[x]>0)and(x<=n)doinc(x);
ifx>nthenbegin
ifmax>vthenmax:
=v;
exit;
end;
ifv>=max-1thenexit;
fork:
=1tos[x,0]dobegin
i:
=s[x,k];
forj:
=1tol[i]doinc(d[a[i,j]]);
dfs(v+1,x+1);
forj:
=1tol[i]dodec(d[a[i,j]]);
end;
end;
begin
{assign(input,'solve.in');reset(input);
assign(output,'solve.out');rewrite(output);}
readln(n,m);
fori:
=1tomdobegin
read(l[i]);
forj:
=1tol[i]dobegin
read(a[i,j]);b[i,a[i,j]]:
=true;
end;
readln;
end;
fori:
=1tomdo
forj:
=1tomdo
if(i<>j)and(l[i]>0)and(l[j]>0)thenbegin
can:
=true;
fork:
=1tol[i]doifnotb[j,a[i,k]]thenbegin
can:
=false;break;
end;
ifcanthenbegin
l[i]:
=0;break;
end;
end;
ans:
=0;
fori:
=1tondobegin
forj:
=1tomdoifb[j,i]thenbegin
inc(s[i,0]);s[i,s[i,0]]:
=j;
end;
ifs[i,0]=1thenifl[s[i,1]]<>0thenbegin
x:
=s[i,1];ans:
=ans+1;
forj:
=1tol[x]doinc(d[a[x,j]]);
l[x]:
=0;
end;
end;
max:
=9999;
dfs(ans,1);
writeln(max);
{close(input);close(output);}
end.
2.迷宫
问题描述:
小希非常喜欢玩迷宫游戏,现在她自己设计了一个迷宫游戏。
在她设计的迷宫中,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。
小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。
比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
数据输入:
输入包含多组数据,每组数据是一个以00结尾的整数对列表,表示了一条通道连接的两个房间的编号。
房间的编号至少为1,且不超过100000。
每两组数据之间有一个空行。
整个文件以两个-1结尾。
数据输出:
对于输入的每一组数据,输出仅包括一行。
如果该迷宫符合小希的思路,那么输出"1",否则输出"0"。
输入输出样例:
Migong.in
68535264
5600
8173628975
74787600
386864
53565200
-1-1
Migong.out
1
1
0
解法:
这道题实际是一道数据结构题,NOIP的数据结构也是很重要的考察内容,比如线性表、哈希表、并查集、树状数组等。
这道题很裸的要求判定图中任意两点是否存在唯一通路,对于具有唯一通路的图而言实际上就是树结构。
根据树的特征可以知道n个节点的树,其必然有只有n-1条边相连,对数据进行初步判断将输入边数不等于节点数n-1的图去掉,剩下来的就是判断图中是否存在回路,如果有回路则必然导致有节点不在一个连通图中,所以实际就是判断图的连通性。
图的连通性判断由很多方法,比如深搜或广搜,比如种子填充算法BloodFill,比如最小生成树算法,当然更高效的还有并查集算法,
下面就是使用并查集解决的参考代码,这道题特别要注意的地方是空集也是可行的!
程序:
programmigong;
vari,j,a,b,max,min,tt,tr,tx,x,y:
longint;
fa,rank:
array[1..100001]oflongint;
map:
array[1..100000]ofboolean;
functionmaxx(x,y:
longint):
longint;
begin
ifx>ythenexit(x);
exit(y);
end;
functionminn(x,y:
longint):
longint;
begin
ifx>ythenexit(y);
exit(x);
end;
functionfind(x:
longint):
longint;
begin
ifx<>fa[x]thenfa[x]:
=find(fa[x]);
find:
=fa[x];
end;
procedureunion(x,y:
longint);
begin
x:
=find(x);
y:
=find(y);
ifrank[x]=y
elsebegin
ifrank[x]=rank[y]theninc(rank[x]);
fa[y]:
=x;
end;
end;
begin
read(a,b);
while(a<>-1)dobegin
fori:
=1to100dofa[i]:
=i;
fillchar(rank,sizeof(rank),0);
fillchar(map,sizeof(map),false);
tr:
=0;tt:
=0;tx:
=0;
min:
=100001;max:
=-1;
while(a<>0)dobegin
inc(tt);{边数}
map[a]:
=true;map[b]:
=true;
max:
=maxx(max,maxx(a,b));
min:
=minn(min,minn(a,b));
union(a,b);
read(a,b);
end;
fori:
=mintomaxdoifmap[i]=truethenbegin
iffa[i]=itheninc(tr);{根节点数目,节点都在一棵树上}
inc(tx);{点的个数}
end;
if((tx-1=tt)and(tr=1))or((max=-1)and(min=100001))thenwriteln
(1)
{利用树的特性}{树为空时,结果为1}
elsewriteln(0);
read(a,b);
end;
end.
3.牛棚安排
【问题描述】
FarmerJohn的N(1<=N<=1000)头奶牛分别居住在农场所拥有的B(1<=B<=20)个牛棚的某一个里。
有些奶牛很喜欢她们当前住的牛棚,而另一些则讨厌再在它们现在所在的牛棚呆下去。
FJ在忍受了若干次奶牛的抱怨后,决定为所有奶牛重新安排牛棚,使最不满的那头奶牛与最高兴的奶牛的心情差异最小,即使这会让所有奶牛都更加郁闷。
每头奶牛都把她对各个牛棚的好感度从高到低排序后告诉了FJ。
当然,如果一头奶牛被安排到的牛棚在她给出的列表中越靠后,她就会越郁闷。
你可以认为奶牛的郁闷指数是她被分配到的牛棚在列表中的位置。
奶牛们是斤斤计较的,她们无法容忍别的奶牛在自己喜欢的牛棚里快乐地生活,而自己却呆在一个自己不喜欢的牛棚里。
每个牛棚都只能容纳一定数量的奶牛。
FJ希望在每个牛棚都没有超出容量限制的前提下,使最郁闷和最高兴的奶牛的郁闷指数的跨度最小。
FJ请你帮他写个程序,来计算这个最小的郁闷指数跨度到底是多少。
【输入】
第1行:
包含2个用空格隔开的整数N和B,分别表示牛和牛棚的数量
第2..N+1行:
每行包含B个用空格隔开的整数,刚好完全包含1..B的整数。
第i+1行的第一个整数,表示奶牛i最喜欢的牛棚编号。
第二个整数表示奶牛i的列表中排在第二位,也就是她第二喜欢的牛棚。
依此类推。
第N+2行:
包含B个用空格隔开的整数,第i个整数表示牛棚i最多能容纳的奶牛的数目。
所有牛棚能容纳奶牛头数的和至少是N。
【输出】
第1行:
输出一个整数,表示所有奶牛中最高兴与最郁闷的牛的郁闷指数跨度
【输入输出样例】
stead.in
stead.out
64
1234
2314
4231
3124
1342
1423
2132
2
【样例说明】
每头奶牛都能被安排进她的第一或第二喜欢的牛棚。
下面给出一种合理的分配方案:
奶牛1和奶牛5住入牛棚1,牛棚2由奶牛2独占,奶牛4住进牛棚3,剩下的奶牛3和奶牛6安排到牛棚4。
解法:
原题模型是二分图匹配的,当然也可以用网络流来解,这里考察的是noip的算法用的是动态规划
varn,m,l,r,ans,i,j:
longint;
a:
array[0..1100,0..30]oflongint;
p:
array[0..30,0..1100]oflongint;
tot:
array[0..30]oflongint;
u:
array[0..30]ofboolean;
functionpd(k:
longint):
boolean;{多重二分匹配图}
vari,jm,j:
longint;
begin
fori:
=ltordobegin
jm:
=a[k,i];
ifp[jm,0]inc(p[jm,0]);p[jm,p[jm,0]]:
=k;
exit(true);
end
elseifnotu[jm]thenbegin
u[jm]:
=true;
forj:
=1top[jm,0]doifpd(p[jm,j])thenbegin
p[jm,j]:
=k;
exit(true);
end;
end;
end;
exit(false);
end;
begin
readln(n,m);
fori:
=1tondobegin
forj:
=1tomdoread(a[i,j]);
readln;
end;
fori:
=1tomdoread(tot[i]);
readln;
ans:
=maxlongint;
forl:
=1tomdobegin{最大高兴指数}
fillchar(p,sizeof(p),0);
r:
=l;
fori:
=1tondobegin{枚举第i头牛}
whiletruedobegin
fillchar(u,sizeof(u),0);
ifpd(i)thenbreak;
inc(r);{最小高兴指数}
ifr>mthenbreak;{全部牛棚都找过}
ifr-l+1>=ansthenbreak;{剪枝}
end;
ifr>mthenbreak;
ifr-l+1>=ansthenbreak;
end;
ifr>mthenbreak;
if(r<=m)and(r-l+1=r-l+1;
end;
writeln(ans);
end.