20111018 模拟赛
题目名称 | Lyric | Trick | Maze | Dormitory |
可执行文件名 | Lyric | Trick | Maze | Dormitory |
输入文件名 | Lyric.in | Trick.in | Maze.in | Dormitory.in |
输出文件名 | Lyric.out | Trick.out | Maze.out | Dormitory.out |
时限 | 1s | 1s | 1s | 1s |
内存限制 | 128M | 128M | 128M | 128M |
测试点数目 | 10 | 10 | 10 | 10 |
测试点分值 | 10 | 10 | 10 | 10 |
题目类型 | 传统 | 传统 | 传统 | 传统 |
Lyric
【问题描述】
痛过以后 才知情已难寻
吾爱至斯 只剩飞花梦影
回首再望 蜀山依旧伫立
看尽浮沉 独饮回忆 ——《少年情》
旋律动听的曲子,伴着意境深远的lyric而显得更加优美。要想学会一首歌,没有一份装订精美的歌词,你让我情何以堪。
你的任务是,将一份歌词,按照给出规则整理好。
【输入格式】
若干行文字(包括按规定格式给出歌曲名,歌词)
每一行格式为 标识+内容
标识[name]表示后接歌曲名
标识[mm:ss]表示后接歌词,其中m,s表示每一位数字,为歌词出现的时间。保证符合正常的计时方式。
若存在时间相同的歌词,则应按规则依次首尾相连在同一行输出,规则如下:
1、 长度短的靠前;
2、 长度相同则字典序小的靠前。
【输出格式】
第一行八个空格+歌曲名
第二行及以后按时间顺序列出歌词
【输入样例】
[00:02]she is the heaven-sent angel you met
[00:05]=.=.=.=.=
[00:04]she is so pretty all over the world
[00:01]she is the one that you never forget
[name]she
[00:03]oh,she must be the reason why God made a girl
【输出样例】
she
she is the one that you never forget
she is the heaven-sent angel you met
oh,she must be the reason why God made a girl
she is so pretty all over the world
=.=.=.=.=
【数据hint】
1、 保证歌曲名和歌词均为英文字母,字符。
2、 保证每一行不超过256个字符
3、 保证输入不超过2000行
//用字符串模拟恶心人
//C处理字符串的空格太麻烦了,还是写P
program lyric;
type
node=record
time,len:longint;s:ansistring;end;
var
a:array[0..2100] of node;i,last,n,p,tt,mm:longint;s,m,t:ansistring;procedure swap(var a,b:node);var
c:node;begin
c:=a;a:=b;b:=c;end;
function cmp(a,b:node):boolean;
begin
if (a.time<b.time) then exit(true)else if (a.time>b.time) then exit(false)else if (a.len<b.len) then exit(true)else if (a.len>b.len) then exit(false)else if (a.s<b.s) then exit(true);exit(false);end;
procedure sort(l,r:longint);
var
i,j:longint;x:node;begin
i:=l;j:=r;x:=a[(l+r) shr 1];
repeat
while (cmp(a[i],x)) do inc(i);while (cmp(x,a[j])) do dec(j);if (i<=j) thenbegin
swap(a[i],a[j]);inc(i);dec(j);end;
until i>j;
if (i<r) then sort(i,r);if (l<j) then sort(l,j);end;
begin
assign(input,'lyric.in');reset(input);
assign(output,'lyric.out');rewrite(output);while (not eof) dobegin
inc(n);readln(s);p:=pos(']',s);a[n].s:=copy(s,p+1,length(s)-p);a[n].len:=length(a[n].s);if (s[2]='n')and(s[3]='a')and(s[4]='m')and(s[5]='e') thenbegin
a[n].time:=-1;end
else
begin
//m:=copy(s,2,pos(':',s)-2);
m:='';m:=m+s[2]+s[3];val(m,mm);t:='';t:=t+s[5]+s[6];//t:=copy(s,pos(':',s)+1,p-pos(':',s)-1);
val(t,tt);a[n].time:=mm*100+tt;end;
end;
sort(1,n);write(' ',a[1].s);last:=-1;for i:=2 to n dobegin
if (a[i].time<>last) thenbegin
writeln;end;
write(a[i].s);last:=a[i].time;end;
writeln;close(input);close(output);end.
Trick
【题目描述】
暴躁的稻草人,最终以自爆来给我们的队伍致命一击,全队血量见底,稻草人也一分为二。还好我们有雨柔妹子,瞬间精力回满。不过事后姜小弟和龙腹黑就开始了报复。
他们读取存档,将若干暴躁的稻草人活捉。然后将它们放到一个迷宫的入口。迷宫是有向图。此刻暴躁的稻草人们在1号位置,而迷宫出口在n号位置。因为稻草人会自爆,所以他每经过一条路数量就会加倍。每条路上有敌人,会消耗稻草人c[i](c[i]为负值);当然有些时候路上也会遇到止血草之类的东西,这时候就可以补充一些稻草人咯(c[i]为正值)。如果小稻草人死光了,那么稻草人也就可以看做是挂了。希望你帮助稻姜龙二人算出用最少的初始稻草人使其能够走出迷宫。
【输入格式】
第一行两个数N(<=50000),M(<=100000)表示点位数与边数。
以下M行,每行三个数a,b,c表示从a到b两点间的边权是c(|c|<=10000)
【输出格式】
输出仅一个整数,表示最小初始稻草人数。
【输入样例】
5 4
1 2 -3
1 3 -6
3 4 1
4 5 -9
【输出样例】
4
//应该还有一种方法是只做一边SPFA,没想清,还是写个二分吧
program trick;
type
edge=record
x,w,next:longint;end;
var
e:array[0..200000] of edge;k:array[0..50000] of longint;d:array[0..50000] of longint;v:array[0..50000] of boolean;f:array[0..1000000] of longint;n,m,i,j,tot,a,b,c:longint;l,r,mid:longint;flag:boolean;procedure add(a,b,c:longint);
begin
inc(tot);e[tot].x:=b;e[tot].w:=c;e[tot].next:=k[a];k[a]:=tot;end;
function check(s:longint):boolean;
var
i,x,t,head,tail,cnt:longint;begin
for i:=1 to n dobegin
d[i]:=-1;v[i]:=false;end;
cnt:=0;d[1]:=s;v[1]:=true;head:=0;tail:=1;f[tail]:=1;while (head<tail) dobegin
inc(head);x:=f[head];v[x]:=false;t:=k[x];if (d[x]<=0) then continue;while (t<>0) dobegin
if (d[e[t].x]=-1) or (d[e[t].x]<d[x]*2+e[t].w) thenbegin
d[e[t].x]:=d[x]*2+e[t].w;if (not v[e[t].x]) thenbegin
v[e[t].x]:=true;inc(tail);f[tail]:=e[t].x;end;
end;
t:=e[t].next;end;
end;
if (d[n]>0) then exit(true) else exit(false);end;
begin
assign(input,'trick.in');reset(input);
assign(output,'trick.out');rewrite(output);readln(n,m);for i:=1 to m dobegin
readln(a,b,c);add(a,b,c);end;
l:=0;r:=200000;while (l<r) dobegin
mid:=(l+r) shr 1;
flag:=check(mid);if not flag then l:=mid+1 else r:=mid;end;
writeln(l);close(input);close(output);end.
Maze
【题目描述】
众所周知(怎么又是众所周知),仙剑的迷宫是难走的要命,某人就在仙四的女罗岩困了很长时间。
我们可以把女罗岩的地图抽象成n*n的地图,我们现在在(1,1)处,而出口在(n,n)。每次行动只能向上下左右移动一格。图中有M个机关,只有打开某个机关之后,与该机关相对应的地方才可以行走。当然,地图中还会有小怪兽,他们能够监视着他所在地区以及上下左右共五个方格,我们不愿意与他们战斗(为了节省时间),所以他们能监视到的地方不可以行走。同样的,地图上的障碍物处也不能经过。
我们需要求出从起点到终点的最少步数。
【输入格式】
第1行,两个整数N, M。表示地图大小为N*N,机关的数量为M。
第2-N+1行,每行N个整数,每个整数i可能是0,-1,-2或者一个正整数。i=0表示该位置为一块空地,i=-1表示该位置为一个障碍物,i=-2表示该位置为一个小怪兽。如果i是一个属于[1,M]的正整数,则表示该位置为一个机关,其编号为i。如果i是一个大于M的正整数,则表示该位置为一个机关控制区域,它由编号为i-M的机关控制。
【输出格式】
一个整数,为走出迷宫所需的最少的步数。
【输入样例】
6 2
0 0 0 -2 -1 2
-1 0 0 0 -1 0
-2 0 0 0 3 3
-2 0 0 -1 -1 4
0 -1 0 0 -1 0
1 0 0 0 -1 0
【输出样例】
24
【样例说明】
地图如下图,S为入口,T为目标,黑色的单元格为障碍物。每个E表示一个小怪兽,(E)为小怪兽的监视范围。K1表示机关1,K2表示机关2。D1表示机关为1的控制区域,D2表示机关为2的控制区域。
最优的路线为(1,1) →(1,2) →(2,2) →(2,3) →(3,3) →(4,3) →(5,3) →(6,3) →(6,2) →(6,1)(破坏供电1) →(6,2) →(6,3) →(5,3) →(4,3) →(3,3) →(3,4) →(3,5) →(3,6) →(2,6) →(1,6)(破坏供电2) →(2,6) →(3,6) →(4.6) →(5,6) →(6,6)
【数据规模】
1<=N<=50
0<=M<=16
//二进制+BFS飘过 #include<cstdio> #include<cstring> #include<cstdlib> int di[5]={0,0,1,0,-1}; int dj[5]={0,1,0,-1,0}; int k[17]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768}; int n,m; int a[52][52]; struct node{ int x,y,n,key; }f[1000000]; bool v[65537][52][52]; int main(){ freopen("maze.in","r",stdin); freopen("maze.out","w",stdout); scanf("%d%d",&n,&m); int t; for (int i=1;i<=n;i++){ for (int j=1;j<=n;j++){ scanf("%d",&t); if (a[i][j]!=-1) a[i][j]=t; if (t==-2){ if (j>1) a[i][j-1]=-1; if (j<n) a[i][j+1]=-1; if (i>1) a[i-1][j]=-1; if (i<n) a[i+1][j]=-1; } } scanf("\n"); } int head=0,tail=1,x,y; f[1].x=1; f[1].y=1; v[0][1][1]=true; while (head<tail){ head++; for (int i=1;i<=4;i++){ x=f[head].x+di[i]; y=f[head].y+dj[i]; t=f[head].key; if (x>0&&y>0&&x<=n&&y<=n&&!v[t][x][y]){ if (x==n&&y==n){ printf("%d\n",f[head].n+1); return 0; } if (a[x][y]==-1||a[x][y]==-2) continue; if (a[x][y]==0){ v[t][x][y]=true; f[++tail].x=x; f[tail].y=y; f[tail].n=f[head].n+1; f[tail].key=f[head].key; continue; } if (a[x][y]>m){ if ((f[head].key & k[a[x][y]-m])==k[a[x][y]-m]){ v[t][x][y]=true; f[++tail].x=x; f[tail].y=y; f[tail].n=f[head].n+1; f[tail].key=f[head].key; continue; } } if (a[x][y]<=m&&a[x][y]>0){ v[t][x][y]=true; f[++tail].x=x; f[tail].y=y; f[tail].n=f[head].n+1; f[tail].key=f[head].key | k[a[x][y]]; v[f[tail].key][x][y]=true; } } } } return 0; }
Dormitory
【题目描述】
小蛮妹子有许多的,什么棉花糖啦,蜥蜴啊,小乌龟啊,只有你想不到的没有她没有的。
小蛮妹子的小宠物都住在一个漂亮的大屋子里,每个人都有自己的床位,但是由于小蛮妹子的宠物太多了,以至于这些宠物之间并不是都互相认识。
这些宠物们也有自己的朋友,这些朋友一直羡慕他们住的漂亮大屋子,于是有一天,小蛮妹子出去玩了,一些小宠物也偷偷出去玩了,那些留守的小宠物们开始招待来访的客人。
这些来客都打算在这里住一晚上,可是安排床位就出了麻烦。每个小宠物都只愿意在自己的直接朋友或自己的床上(如果它是小蛮的宠物)睡觉,且一物睡一张床。
询问是否能有一个方案来满足所有在留宿的宠物都能住宿。
【输入格式】
第一行一个数 T 表示数据组数。
接下来 T 组数据。
每组数据第一行一个数 n 表示涉及到的总宠物数(包括小蛮的宠物和来客)。
接下来一行 n 个数,第 i 个数表示第 i 个个宠物是否是在小蛮的宠物 (0 表示不是,1 表示是)。再接下来一行 n 个数,第 i 个数表示第 i 个人是否出去玩(0 表示不出去,1 表示出去)注意如果第 i 个人不是小蛮的宠物,那么这个位置上的数是一个随机的数,你应该在读入以后忽略它)。
接下来 n 行,每行 n 个数,第 i 行第 j 个数表示 i 和 j 是否认识 (1 表示认识,0 表示不认识,第 i 行 i 个的值为 0,但是显然自己还是可以睡自己的床),认识的关系是
相互的。
【输出格式】
每一行对应每组数据
若存在方案满足条件 输出 ^.^ ,否则输出 T.T (只有三个字符,没有空格等其他内容)
【输入样例】
1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0
【输出样例】
^.^
【数据hint】
对于 30% 的数据满足 1 ≤ n ≤ 12。
对于 100% 的数据满足 1 ≤ n ≤ 50,1 ≤ T ≤ 20。
//或是个二分图最大匹配吧 #include <cstdio> #include <cstring> int T; int n; int tot; int map[60][60]; int list[60]; bool out[60]; int match[60]; bool use[60]; bool dfs(int x){ for (int i=1;i<=n;i++){ if (list[i] && map[x][i] && !use[i]){ use[i]=true; if (match[i]==0 || dfs(match[i])){ match[i]=x; return true; } } } return false; } int main(){ freopen("dormitory.in","r",stdin); freopen("dormitory.out","w",stdout); scanf("%d",&T); while (T--){ memset(list,0,sizeof(list)); memset(out,0,sizeof(out)); memset(map,0,sizeof(map)); scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%d",&list[i]); } tot=n; for (int i=1;i<=n;i++){ int x; scanf("%d",&x); if (list[i] && x==1){ out[i]=true; tot--; } } for (int i=1;i<=n;i++){ for (int j=1;j<=n;j++){ scanf("%d",&map[i][j]); } scanf("\n"); } for (int i=1;i<=n;i++) if (list[i]==1) map[i][i]=1;else map[i][i]=0; memset(match,0,sizeof(match)); int ans=0; for (int i=1;i<=n;i++){ if (!out[i]){ memset(use,0,sizeof(use)); if (dfs(i)) ans++; } } if (ans==tot) puts("^.^");else puts("T.T"); } return 0; }