这次比赛没有AK的,120分的有57人,我110分,zzm神犇第一题比我多被坑一个点,但是人家第二题想到正解。
A 穿越七色虹
二分以后判定是个线段覆盖。忘记去掉在x0右边的区间WA第一个和第三个点,改了以后WA5个点,不想调了。
program rainbow;
uses math;
const FileName='rainbow';
var x,r,a,b:array[0..10] of extended;temp,ra,rb,la,lb,left,right,mid,x0,h:extended;i,time:longint;procedure swap(var x,y:extended);var t:extended;
begin t:=x;x:=y;y:=t;end;function cmp(i,j:longint):boolean;
begin
if a[i]<a[j] then exit(true);if a[i]>a[j] then exit(false);if b[i]<b[j] then exit(true);if b[i]>b[j] then exit(false);exit(true);end;
function check(n:extended):boolean;
var tot,i,j:longint;
range,nr,delta:extended;begin tot:=0;
for i:=1 to 7 doif r[i]+n>h thenbegin
nr:=r[i]+n;delta:=sqrt(nr*nr-h*h);inc(tot);a[tot]:=x[i]-delta;b[tot]:=x[i]+delta;if a[tot]>x0 then dec(tot);end;
if tot=0 then exit(false);//sort
for i:=1 to 6 dofor j:=i to 7 doif not cmp(i,j)then beginswap(a[i],a[j]);swap(b[i],b[j]);end;
//work
if a[1]>0 then exit(false);range:=b[1];for i:=2 to tot doif a[i]<range
then range:=max(b[i],range)
else exit(false);
if range>x0 then exit(true)else exit(false);
end;
begin
readln(h,x0);right:=31623;left:=0;time:=0;for i:=1 to 7 do beginreadln(x[i],r[i]);la:=x[i];lb:=x0-x[i];ra:=sqrt(la*la+h*h+10);rb:=sqrt(lb*lb+h*h+10);if(ra>r[i])or(rb>r[i])then begintemp:=-1E6;if ra*ra-la*la>=h*h then temp:=max(temp,ra-r[i]);if rb*rb-lb*lb>=h*h then temp:=max(temp,rb-r[i]);if temp>0 then right:=min(right,temp);end;
end;
right:=right+h;if check(0)
then writeln('0.00')
else beginwhile(abs(right-left)>1E-6)and(time<=10000)do
begin
inc(time);mid:=(left+right)/2;if check(mid)
then right:=mid
else left:=mid;
end;
writeln(right:2:2);end;
end.
B 四叶草魔杖
看数据范围蒙了个状压DP求最优哈密顿路,骗到30分。据说直接MST能80?
program clover;
uses math;
const FileName='clover';
inf=maxlongint div 2;
var u,v,bitset,ans,n,m,fall,i,p,q,t,tot:longint;
f:array[0..16,0..$FFFF] of longint;w:array[0..16,0..16] of longint;a:array[0..16] of longint;begin
readln(n,m);fall:=1<<n-1;ans:=inf;filldword(w,sizeof(w) shr 2, -1);
filldword(f,sizeof(f) shr 2,inf);
for i:=1 to n do read(A[i]);for i:=1 to m dobegin
readln(p,q,t);w[p][q]:=t;w[q][p]:=t;end;
for i:=0 to n-1 do f[i][1<<i]:=0;for bitset:=0 to fall dofor u:=0 to n-1 do if((bitset shr u)and 1)=1 thenfor v:=0 to n-1 do if(((bitset shr v)and 1)=1)and(w[v][u]<>-1)then f[u][bitset]:=min(f[v][bitset xor 1<<u]+w[v][u],f[u][bitset]);for i:=0 to n-1 doans:=min(f[i][fall],ans);if ans<>inf
then writeln(ans)
else writeln('Impossible');
end.
等会学一下正解。orz zzm神犇。由于MST搞完cnt不会比N大,所以秒过。应该意识到这是一个MST删边的问题。首先一个MST是可以满足能量的要求的。然后答案应该是几个子图的MST,每个子图sigma(a[i])=0,然后枚举边的所有组合,BFS验证即可。
#01: Accepted (0ms, 700KB)
#02: Accepted (0ms, 700KB)
#03: Accepted (0ms, 700KB)
#04: Accepted (0ms, 700KB)
#05: Accepted (0ms, 700KB)
#06: Accepted (0ms, 700KB)
#07: Accepted (0ms, 700KB)
#08: Accepted (0ms, 700KB)
#09: Accepted (0ms, 700KB)
#10: Accepted (0ms, 700KB)
Accepted / 100 / 0ms / 700KB
program clover;
uses math;
const FileName='clover';
inf=maxlongint div 2;
var temp,cnt,bitset,ans,n,m,fall,i,j,vi,ui,t,tot:longint;
Q,father:array[0..16] of longint;map:array[0..16,0..16] of longint;a:array[0..16] of longint;u,v,w,new:array[0..120] of longint;vis:array[0..16] of boolean;procedure swap(var a,b:longint);var t:longint;begin t:=a;a:=b;b:=t;end;function find(x:longint):longint;
var t:longint;
begin
if father[x]=x then exit(x);t:=find(father[x]);father[x]:=t;exit(t);end;
procedure union(x,y:longint);
begin father[find(x)]:=find(y);end;function check(bitset:longint;var sum:longint):boolean;var cur,h,t,i,j,temp:longint;
begin sum:=0;
fillchar(vis,sizeof(vis),false);for i:=0 to cnt doif(((bitset>>i)and 1)=1)then inc(sum,w[new[i]]);
for i:=0 to n-1 doif not vis[i]then beginh:=0;t:=1;Q[1]:=i;vis[i]:=true;temp:=a[i];while h<t do begininc(h);cur:=Q[h];for j:=0 to n-1 doif(not vis[j])and(map[cur][j]<>-1)and(((bitset shr map[cur][j])and 1)=1)then begininc(t);Q[t]:=j;vis[j]:=true;inc(temp,a[j]);end;
end;
if temp<>0 then exit(false);end;
exit(true);end;
begin
readln(n,m);fall:=(1<<n)-1;ans:=inf;cnt:=-1;filldword(map,sizeof(map) shr 2, -1);
for i:=0 to n-1 dobegin
read(A[i]);father[i]:=i;end;
for i:=1 to m dobegin
readln(vi,ui,t);u[i-1]:=vi;v[i-1]:=ui;w[i-1]:=t;end;
for i:=0 to m-2 dofor j:=i to m-1 doif w[j]<w[i]
then beginswap(u[i],u[j]);swap(v[i],v[j]);swap(w[i],w[j]);end;
for i:=0 to m-1 doif find(v[i])<>find(u[i])
then begininc(cnt);new[cnt]:=i;map[v[i]][u[i]]:=cnt;map[u[i]][v[i]]:=cnt;union(v[i],u[i]);end;
if(cnt=-1)
then beginif check(0,temp)
then writeln(0)
else writeln('Impossible');
end
else beginfor i:=0 to (1<<(cnt+1))-1 doif check(i,temp)
then ans:=min(ans,temp);
if ans<>inf
then writeln(ans)
else writeln('Impossible');
end;
end.
C 圣主的考验
知道是DP而不会做的感觉,无力啊。