线性规划与网络流4 魔术球问题
算法实现题 8-4 魔术球问题(习题 8-14)
问题描述:
假设有 n 根柱子,现要按下述规则在这 n 根柱子中依次放入编号为 1,2,3,…的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何 2 个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在 n 根柱子上最多能放多少个球。例如,在 4 根柱子上最多可
放 11 个球。
?编程任务:
对于给定的 n,计算在 n 根柱子上最多能放多少个球。
?数据输入:
由文件 input.txt 提供输入数据。文件第 1 行有 1 个正整数 n,表示柱子数。
?结果输出:
程序运行结束时,将 n 根柱子上最多能放的球数以及相应的放置方案输出到文件
output.txt 中。文件的第一行是球数。接下来的 n 行,每行是一根柱子上的球的编号。
输入文件示例
输出文件示例
input.txt
4
output.txt
11
1 8
2 7 9
3 6 10
4 5 11
注意几点:
1.注意拆点前后数值的变化,并且是时刻注意
2.既然已经知道他的最小路径覆盖是n,那么就不需要去找起始点,就用开标记数组以及后继数组的方式遍历即可
代码:
1 const inf=maxlongint; 2 type node=record 3 from,go,next,v:longint; 4 end; 5 arrtype=array[0..200000] of longint; 6 var e:array[0..200000] of node; 7 head,h,q,a,cur,go:arrtype; 8 i,j,n,m,ans,maxflow,tot,l,r,s,t,x,y:longint; 9 p,v,mark:array[0..20000] of boolean; 10 function min(x,y:longint):longint; 11 begin 12 if x<y then exit(x) else exit(y); 13 end; 14 procedure sort(var a:arrtype;l,r:longint); 15 var i,j,m,temp:longint; 16 begin 17 i:=l;j:=r;m:=a[(i+j)>>1]; 18 repeat 19 while a[i]<m do inc(i); 20 while a[j]>m do dec(j); 21 if i<=j then 22 begin 23 temp:=a[i];a[i]:=a[j];a[j]:=temp; 24 inc(i);dec(j); 25 end; 26 until i>j; 27 if i<r then sort(a,i,r); 28 if j>l then sort(a,l,j); 29 end; 30 procedure ins(x,y,z:longint); 31 begin 32 inc(tot); 33 e[tot].from:=x;e[tot].go:=y;e[tot].v:=z;e[tot].next:=head[x];head[x]:=tot; 34 end; 35 procedure insert(x,y,z:longint); 36 begin 37 ins(x,y,z);ins(y,x,0); 38 end; 39 function bfs:boolean; 40 var i,x,y:longint; 41 begin 42 fillchar(h,sizeof(h),0); 43 l:=0;r:=1;q[1]:=s;h[s]:=1; 44 while l<r do 45 begin 46 inc(l); 47 x:=q[l]; 48 i:=head[x]; 49 while i<>0 do 50 begin 51 y:=e[i].go; 52 if (e[i].v<>0) and (h[y]=0) then 53 begin 54 h[y]:=h[x]+1; 55 inc(r);q[r]:=y; 56 end; 57 i:=e[i].next; 58 end; 59 end; 60 exit (h[t]<>0); 61 end; 62 function dfs(x,f:longint):longint; 63 var i,y,used,tmp:longint; 64 begin 65 if x=t then exit(f); 66 used:=0; 67 i:=cur[x]; 68 while i<>0 do 69 begin 70 y:=e[i].go; 71 if (h[y]=h[x]+1) and (e[i].v<>0) then 72 begin 73 tmp:=dfs(y,min(e[i].v,f-used)); 74 dec(e[i].v,tmp);if e[i].v<>0 then cur[x]:=i; 75 inc(e[i xor 1].v,tmp); 76 inc(used,tmp); 77 if used=f then exit(f); 78 end; 79 i:=e[i].next; 80 end; 81 if used=0 then h[x]:=-1; 82 exit(used); 83 end; 84 procedure dinic; 85 begin 86 while bfs do 87 begin 88 for i:=s to t do cur[i]:=head[i]; 89 inc(maxflow,dfs(s,inf)); 90 end; 91 end; 92 procedure init; 93 begin 94 tot:=1; 95 readln(n);m:=n; 96 fillchar(p,sizeof(p),false); 97 for i:=1 to 120 do p[i*i]:=true; 98 s:=0;t:=20001; 99 for i:=1 to n do begin insert(s,i,1);insert(i+10000,t,1);end; 100 for i:=1 to n-1 do 101 for j:=i+1 to n do 102 if p[i+j] then insert(i,j+10000,1); 103 end; 104 procedure main; 105 begin 106 maxflow:=0; 107 dinic; 108 while true do 109 begin 110 inc(m);insert(s,m,1);insert(m+10000,t,1); 111 for i:=1 to m-1 do if p[i+m] then insert(i,m+10000,1); 112 dinic; 113 if m-maxflow>n then break; 114 end; 115 writeln(m-1); 116 //for i:=2 to tot do with e[i] do if go=0 then writeln(from,' ',go,' ',v,' ',next); 117 for x:=1 to m-1 do 118 begin 119 i:=head[x]; 120 while i<>0 do 121 begin 122 y:=e[i].go; 123 if e[i].v=0 then begin go[x]:=y-10000;break;end; 124 i:=e[i].next; 125 end; 126 end; 127 fillchar(mark,sizeof(mark),false); 128 for i:=1 to m-1 do 129 begin 130 if mark[i] then continue; 131 x:=i; 132 while x<>-10000 do 133 begin 134 mark[x]:=true; 135 write(x,' '); 136 x:=go[x]; 137 end; 138 writeln; 139 end; 140 end; 141 begin 142 assign(input,'ball.in');assign(output,'ball.out'); 143 reset(input);rewrite(output); 144 init; 145 main; 146 close(input);close(output); 147 end. 148 149