这道题真的不难,但是细节挺多(具体见程序)
题目本身而言,显然是个费用流模型(或者写KM)
1 type node=record 2 point,next,flow,cost:longint; 3 end; 4 5 var p,x,y,pre,cur,d:array[0..80] of longint; 6 v:array[0..80] of boolean; 7 q:array[0..500010] of longint; 8 edge:array[0..200010] of node; 9 a:array[0..80,0..80] of longint; 10 na:array[0..80] of string[21]; 11 t,n,i,len,j,k:longint; 12 ef:boolean; 13 s:string; 14 ch:char; 15 16 function find(x:string):longint; 17 var i:longint; 18 begin 19 for i:=1 to 2*n do 20 if na[i]=x then exit(i); 21 end; 22 23 function check(l,r:longint):boolean; 24 var i:longint; 25 begin 26 for i:=1 to 2*n do 27 if (i<>l) and (i<>r) then 28 if ((x[i]<=x[l]) and (x[i]>=x[r])) or ((x[i]>=x[l]) and (x[i]<=x[r])) then 29 if ((y[i]<=y[l]) and (y[i]>=y[r])) or ((y[i]>=y[l]) and (y[i]<=y[r])) then 30 if (x[i]-x[l])*(y[i]-y[r])=(x[i]-x[r])*(y[i]-y[l]) then 31 begin //注意是线段上的点 32 exit(false); 33 end; 34 exit(true); 35 end; 36 37 procedure add(x,y,f,w:longint); 38 begin 39 inc(len); 40 edge[len].point:=y; 41 edge[len].flow:=f; 42 edge[len].cost:=w; 43 edge[len].next:=p[x]; 44 p[x]:=len; 45 end; 46 47 function spfa:boolean; 48 var i,j,f,r,x,y:longint; 49 begin 50 for i:=1 to t do 51 d[i]:=-100000007; 52 d[0]:=0; 53 f:=1; 54 r:=1; 55 fillchar(v,sizeof(v),false); 56 q[1]:=0; 57 v[0]:=true; 58 while f<=r do 59 begin 60 x:=q[f]; 61 v[x]:=false; 62 i:=p[x]; 63 while i<>-1 do 64 begin 65 y:=edge[i].point; 66 if edge[i].flow>0 then 67 if d[x]+edge[i].cost>d[y] then 68 begin 69 pre[y]:=x; 70 cur[y]:=i; 71 d[y]:=d[x]+edge[i].cost; 72 if not v[y] then 73 begin 74 inc(r); 75 q[r]:=y; 76 v[y]:=true; 77 end; 78 end; 79 i:=edge[i].next; 80 end; 81 inc(f); 82 end; 83 if d[t]=-100000007 then exit(false) else exit(true); 84 end; 85 86 function maxcost:longint; 87 var i,j:longint; 88 begin 89 maxcost:=0; 90 while spfa do 91 begin 92 maxcost:=maxcost+d[t]; 93 i:=t; 94 while i<>0 do 95 begin 96 j:=cur[i]; 97 dec(edge[j].flow); 98 inc(edge[j xor 1].flow); 99 i:=pre[i]; 100 end; 101 end; 102 end; 103 104 begin 105 len:=-1; 106 fillchar(p,sizeof(p),255); 107 readln(k); 108 readln(n); 109 for i:=1 to 2*n do 110 begin 111 readln(x[i],y[i],ch,na[i]); 112 for j:=1 to length(na[i]) do 113 na[i][j]:=upcase(na[i][j]); //注意不区分大小写 114 end; 115 t:=2*n+1; 116 for i:=1 to n do 117 begin 118 add(0,i,1,0); 119 add(i,0,0,0); 120 add(i+n,t,1,0); 121 add(t,i+n,0,0); 122 end; 123 124 for i:=1 to n do 125 for j:=n+1 to 2*n do 126 a[i,j]:=1; //注意 127 ef:=true; 128 while ef do 129 begin 130 s:=''; 131 read(ch); 132 while ch<>' ' do 133 begin 134 s:=s+upcase(ch); 135 if s='END' then ef:=false; //大坑,有的人名字里会带end 136 read(ch); 137 if not ef and (ord(ch)>=65) then 138 ef:=true 139 else if not ef then break; 140 end; 141 if not ef then break; 142 i:=find(s); 143 s:=''; 144 read(ch); 145 while ch<>' ' do 146 begin 147 s:=s+upcase(ch); 148 read(ch); 149 end; 150 j:=find(s); 151 readln(a[i,j]); 152 a[j,i]:=a[i,j]; 153 end; 154 for i:=1 to n do 155 for j:=n+1 to 2*n do 156 if (sqr(x[i]-x[j])+sqr(y[i]-y[j])<=sqr(k)) and check(i,j) then 157 begin 158 add(i,j,1,a[i,j]); 159 add(j,i,0,-a[i,j]); 160 end; 161 writeln(maxcost); 162 end.