BZOJ2595:[WC2008]游览计划
Description
Input
第一行有两个整数,N和 M,描述方块的数目。
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。
Output
由 N + 1行组成。第一行为一个整数,表示你所给出的方案
中安排的志愿者总数目。
接下来 N行,每行M 个字符,描述方案中相应方块的情况:
z ‘_’(下划线)表示该方块没有安排志愿者;
z ‘o’(小写英文字母o)表示该方块安排了志愿者;
z ‘x’(小写英文字母x)表示该方块是一个景点;
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。
Sample Input
4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
Sample Output
6
xoox
___o
___o
xoox
xoox
___o
___o
xoox
HINT
对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内
题解:
裸裸的斯坦纳树,只是多了要求具体方案。
将需要联通的景点是否在联通块中压缩为状态k。F[i,k]表示已i点为中心的联通块,包含的景点为状态k,所需要的最小费用。
对于相邻的点i,j,可进行这样的转移:F[i,x]+F[j,y]——>F[i,x xor y]与F[j,x xor y]。对此进行spfa,记录其是由哪两个情况转移来的。
为了减少复杂度,转移时保证x and y=0。
见证奇迹:
(其实有种更优的DP写法,外加PASCAL在BZOJ中不享有明显的O2优化)
代码:
1 const 2 fx:array[0..3]of longint=(-1,0,1,0); 3 fy:array[0..3]of longint=(0,-1,0,1); 4 var 5 i,j,k:longint; 6 n,m,ans1,ans2,cnt,s,e,fro1,fro2,to1,to2,pos:longint; 7 map,map2:array[0..10,0..10]of longint; 8 a:array[0..10,0..10,0..1024,0..3]of longint; 9 bo:array[0..10,0..10,0..1024]of longint; 10 f:array[0..1000001,1..3]of longint; 11 procedure ss(x,y,z:longint); 12 begin 13 map2[x,y]:=1; 14 if(a[x,y,z,1]=0)or(a[x,y,z,2]=0)then exit; 15 ss(x,y,a[x,y,z,3]); 16 ss(a[x,y,z,1],a[x,y,z,2],z xor a[x,y,z,3]); 17 end; 18 procedure wh(x,y:longint); 19 begin 20 if x>cnt then 21 begin 22 if a[fro1,fro2,pos,0]+a[to1,to2,y,0]<a[to1,to2,pos or y,0] then 23 begin 24 a[to1,to2,pos or y,0]:=a[fro1,fro2,pos,0]+a[to1,to2,y,0]; 25 a[to1,to2,pos or y,1]:=fro1; a[to1,to2,pos or y,2]:=fro2; 26 a[to1,to2,pos or y,3]:=y; 27 if bo[to1,to2,pos or y]=0 then 28 begin 29 bo[to1,to2,pos or y]:=1; 30 inc(e); if e=1000001 then e:=1; 31 f[e,1]:=to1; f[e,2]:=to2; f[e,3]:=pos or y; 32 end; 33 end; 34 if a[fro1,fro2,pos,0]+a[to1,to2,y,0]<a[fro1,fro2,pos or y,0] then 35 begin 36 a[fro1,fro2,pos or y,0]:=a[fro1,fro2,pos,0]+a[to1,to2,y,0]; 37 a[fro1,fro2,pos or y,1]:=to1; a[fro1,fro2,pos or y,2]:=to2; 38 a[fro1,fro2,pos or y,3]:=pos; 39 if bo[fro1,fro2,pos or y]=0 then 40 begin 41 bo[fro1,fro2,pos or y]:=1; 42 inc(e); if e=1000001 then e:=1; 43 f[e,1]:=fro1; f[e,2]:=fro2; f[e,3]:=pos or y; 44 end; 45 end; 46 exit; 47 end; 48 if pos and(1 shl(x-1))=0 then 49 wh(x+1,y or(1 shl(x-1))); 50 wh(x+1,y); 51 end; 52 begin 53 readln(n,m); 54 for i:=1 to n do 55 for j:=1 to m do 56 for k:=0 to 1023 do a[i,j,k,0]:=maxlongint div 2; 57 for i:=1 to n do 58 for j:=1 to m do 59 begin 60 read(map[i,j]); 61 if map[i,j]=0 then 62 begin 63 inc(e); inc(cnt); f[e,1]:=i; f[e,2]:=j; f[e,3]:=1 shl(cnt-1); 64 a[i,j,f[e,3],0]:=0; bo[i,j,f[e,3]]:=1; 65 end else 66 begin 67 inc(e); f[e,1]:=i; f[e,2]:=j; f[e,3]:=0; 68 a[i,j,0,0]:=map[i,j]; bo[i,j,0]:=1; 69 end; 70 end; 71 a[0,0,(1 shl cnt)-1,0]:=maxlongint; 72 while s<>e do 73 begin 74 inc(s); if s=1000001 then s:=1; 75 fro1:=f[s,1]; fro2:=f[s,2]; pos:=f[s,3]; 76 if(pos=(1 shl cnt)-1)and(a[fro1,fro2,pos,0]<a[ans1,ans2,pos,0]) 77 then begin ans1:=fro1; ans2:=fro2; end; 78 bo[fro1,fro2,pos]:=0; 79 for i:=0 to 3 do 80 if(fro1+fx[i]>=1)and(fro1+fx[i]<=n)and(fro2+fy[i]>=1)and(fro2+fy[i]<=m) 81 then begin 82 to1:=fro1+fx[i]; to2:=fro2+fy[i]; 83 wh(1,0); 84 end; 85 end; 86 writeln(a[ans1,ans2,(1 shl cnt)-1,0]); 87 ss(ans1,ans2,(1 shl cnt)-1); 88 for i:=1 to n do 89 begin 90 for j:=1 to m do 91 begin 92 if map[i,j]=0 then write('x') 93 else if map2[i,j]=1 then write('o') 94 else write('_'); 95 end; 96 writeln; 97 end; 98 end.