首页 > 代码库 > USACO 2014 FEB 银组

USACO 2014 FEB 银组

1.自动打字{Silver1}

【问题描述】

贝西新买了手机,打字不方便,请设计一款应用,帮助她快速发消息。

字典里有W(W<=30000)个小写字母构成的单词,所有单词的字符总数量不超过1,000,000,这些单词是无序的。现在给出N(1 <= N <= 1000)个询问,每个询问i包含一个的字符串s_i(每个字符串最多包含1000个字符)和一个整数K_i,对于所有以s_i为前缀的单词,其中按字典序排序后的第K_i个单词,求该单词在原字典里的序号。

【文件输入】

第一行为两个整数W和N。

接下来2..W+1行,每行一个单词;

接下来W+2..W+N+1行,一个整数和一个字符串,分别表示K_i和s_i。

【文件输出】

   输出共N行,每行一个整数,表示位置,如果无解则输出-1。

【输入样例】

10 3

dab

ba

ab

daa

aa

aaa

aab

abc

ac

dadba

4 a

2 da

4 da

【输出样例】

3

1

-1

【样例说明】

以a为前缀的单词有{aa,aaa,aab,ab,abc,ac},第4个是ab,它在原字典中的位置是3,以da为前缀的单词有{daa,dab,dadba},第2个是dab,它在原字典中的位置是1,以da为前缀的第4个单词不存在。

2. 路障{silver2}

【问题描述】

农民约翰的农场n(1 <= N <= 250)个结点,有M(1 <= M <= 25,000)条带权值的有向边,任意两个结点之间最多有一条边相连,任意两个结点之间都有连通的路径。他的家在结点1,谷仓在结点n,他每天都从家选择最短的路径走到谷仓。

牛们开始捣乱,选择在某一条边上放置路障,使得该边的权值变为原来的2倍。求最大能使约翰多走多少路。

【文件输入】

第一行,两个用空格隔开在整数N和M。

接下来M行,每行3个整数,A_j,B_j和L_j,分别表示一条边的两个结点和权值(权值是1...1,000,000的整数)。

【文件输出】

一个整数,表示最大值。

【输入样例】

5 7

2 1 5

1 3 1

3 2 8

3 5 7

3 4 3

2 4 7

4 5 2

【输出样例】

2

【样例说明】

原来的最短路径是1-3-4-5,总长为6,将路障放置3和4之间的边上,使得该边的权值变为6,则最短路径变为1-3-5,总长为8,增加了长度2。

 

第一题字符串处理 排序

 

 

var w,i,j,k,m,n,p:longint;    a:array[0..30000] of string;    num:array[0..30000] of longint;    len:longint;    s:string;    pre:string;    ch:char;    //t:array[0..26,30000] of string;procedure sort(l,r: longint);      var         i,j: longint;         x,y: string;         z:longint;begin         i:=l;         j:=r;         x:=a[(l+r) div 2];         repeat           while a[i]<x do            inc(i);           while x<a[j] do            dec(j);           if not(i>j) then             begin                y:=a[i];                a[i]:=a[j];                a[j]:=y;                z:=num[i];                num[i]:=num[j];                num[j]:=z;                inc(i);                j:=j-1;             end;         until i>j;         if l<j then           sort(l,j);         if i<r then           sort(i,r);end;begin assign(input,auto.in); reset(input); assign(output,auto.out); rewrite(output); readln(N,w); for i:=1 to n do  readln(a[i]); for i:=1 to n do  num[i]:=i; sort(1,n); for i:=1 to w do  begin   readln(k,ch,pre);   //delete(pre,1,1);   for j:=1 to n do    begin     if a[j][1]=pre[1] then      begin       s:=copy(a[j+k-1],1,length(pre));       if s=pre then       begin       writeln(num[j+k-1]);       break;       end       else       begin writeln(-1);       break;       end;      end;    end;  end;close(input);close(output);end.

第二题

 

 可以知道改变的边一定是在原最短路径上,不然John就可以按原最短路径走了。

先做一边Dijkstra 记下路径,再枚举路径,做Dijkstra。

var i,j,n,m,s,t,p,min,x,y,k,l:longint;    a:array[0..1000,0..1000]of longint;    d,pre:array[0..1000]of longint;    v:array[0..1000]of boolean;    a1,b1:longint;    ok:boolean;procedure dijkstra(s:longint);begin    fillchar(d,sizeof(d),$7f);    fillchar(v,sizeof(v),false);    d[s]:=0;    for j:=1 to n do begin        min:=maxlongint;        for i:=1 to n do            if (not v[i]) and (d[i]<min) then            begin                p:=i;                min:=d[i];            end;        v[p]:=true;        for i:=1 to n do            if (not v[i])and(a[p,i]<>0)and            (d[p]+a[p,i]<d[i]) then            begin             d[i]:=d[p]+a[p,i];             if not ok then pre[i]:=p;            end;    end;end;beginassign(input,rblock.in);reset(input);assign(output,rblock.out);rewrite(output);   fillchar(pre,sizeof(pre),0);   read(n,m);   for j:=1 to m do       begin        read(a1,b1,l);        if (l<a[a1,b1]) or (a[a1,b1]=0)  then begin         a[a1,b1]:=l;         a[b1,a1]:=l;        end;       end;    dijkstra(1);    ok:=true;    x:=d[n];    k:=n;repeat a[k,pre[k]]:=2*a[k,pre[k]]; a[pre[k],k]:=a[k,pre[k]]; dijkstra(1); if d[n]>y then  y:=d[n]; a[k,pre[k]]:=a[k,pre[k]] div 2; a[pre[k],k]:=a[k,pre[k]]; k:=pre[k];until k=0;writeln(y-x);close(input);close(output);end.

 

USACO 2014 FEB 银组