Description
100%R,C≤20,N≤200
R,C
为棋盘大小,
N
<script type="math/tex" id="MathJax-Element-48">N</script>为骑士数。
Analysis
我还真是中了网络流的毒啊啊啊啊啊啊
限制条件做多了,中毒了
显然的思路是预处理所有点到棋盘上任意位置的最小移动次数。
然后呢?怎么办?
本蒟蒻乱搞,搞出了一个神奇的费用流,开心滴码,愉快滴调不出来。。。
没办法,正要放弃,发现自己突然SB了。
枚举两个点AB,直接按到A的距离-B的距离排序贪心选就好了。
至于这样为甚么是对的,显然。
Code
垫底代码,献上
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=210,R=22,
fx[8][2]={{-1,-2},{-1,2},{1,-2},{1,2},{-2,-1},{-2,1},{2,-1},{2,1}};
int n,r,c,S,h[N],dis[N][R][R];
bool bz[N];
struct node
{
int x,y;
}a[N],b[N];
bool cmp(node a,node b){return a.x-a.y<b.x-b.y;}
void dfs(int x,int y,int k)
{
if(dis[S][x][y]<=k) return;
dis[S][x][y]=k;
fo(i,0,7)
{
int xx=x+fx[i][0],yy=y+fx[i][1];
if(xx<1 || xx>r || yy<1 || yy>c) continue;
dfs(xx,yy,k+1);
}
}
int main()
{
scanf("%d %d %d",&n,&r,&c);
fo(i,1,n)
{
S=i;
scanf("%d %d",&a[i].x,&a[i].y);
memset(dis[i],127,sizeof(dis[i]));
dfs(a[i].x,a[i].y,0);
}
int ans=2147483647;
fo(x1,1,r)
fo(y1,1,c)
fo(x2,1,r)
fo(y2,1,c)
if(!(x1==y1 && x2==y2))
{
fo(i,1,n) b[i].x=dis[i][x1][y1],b[i].y=dis[i][x2][y2];
sort(b+1,b+n+1,cmp);
int t=0;
fo(i,1,n/2) t+=b[i].x;
fo(i,n/2+1,n) t+=b[i].y;
ans=min(ans,t);
}
printf("%d",ans);
return 0;
}