本题的难点是“移动过程中不能出现多颗棋子同时在某一格的情况”。

  事实上,可以忽略此条件,因为棋子是相同的,我们可以用合法的等效方案替代一棋子越过另一棋子的情况:A、B、C三格,A能在一步走到B,B也能在一步走到C。

在A的棋子需要走到存在棋子的B,接着走到C。此情形我们可以看成在B的棋子先走到C,接着在A的棋子走到B。

  BFS预处理出每个初始位置走到每个终止位置的最少步数。

  把初始位置抽象成二部图的左部,终止位置抽象成二部图的右部,左右之间边权为最少步数。

  那么次二部图的完备匹配对应着一种方案,匹配的边权和对应最少总步数。

  可用最佳匹配解决。

期望得分:

70(裸费用流)

90(n^4的KM算法)

100(n^3的KM算法)

//跑费用流,极限90(不会KM~~)

//by shenben
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#define setfire(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout);
using namespace std;
const int N=;
const int Z=;
const int inf=0x3f3f3f3f;
char mp[N][N];bool vis[N][N];int id[N][N];
int n,m,k,S,T,a,b,ans,f[Z][];
int dx[],dy[];
struct M{
int x,y,step;
M(int x=,int y=,int step=):x(x),y(y),step(step){}
};
struct edge{int v,next,cap,cost;}e[Z*Z*];int tot=,head[Z<<];bool mark[Z<<];
int dist[Z][Z],prev[Z<<],dis[Z<<],q[Z*];
inline int read(){
register int x=;register char ch=getchar();
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x;
}
inline void add(int x,int y,int z,int cost){
e[++tot].v=y;e[tot].cap=z;e[tot].cost=cost;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].cap=;e[tot].cost=-cost;e[tot].next=head[y];head[y]=tot;
}
inline void init(){
n=read();m=read();k=read();a=read();b=read();
if(n==&&m==&&k==&&a==&&b==){puts("");exit();}
dx[]=a;dx[]=a;dx[]=-a;dx[]=-a;dx[]=b;dx[]=b;dx[]=-b;dx[]=-b;
dy[]=b;dy[]=-b;dy[]=b;dy[]=-b;dy[]=-a;dy[]=a;dy[]=a;dy[]=-a;
for(int i=;i<=n;i++) scanf("%s",mp[i]+);
for(int i=;i<=k;i++) f[i][]=read(),f[i][]=read();
for(int i=,x,y;i<=k;i++) x=read(),y=read(),id[x][y]=i;
}
inline bool inside(int x,int y){
return (x>&&x<=n&&y>&&y<=m);
}
inline void bfs(int num){
int cnt=,sx=f[num][],sy=f[num][];
memset(vis,,sizeof vis);
queue<M>q;q.push(M(sx,sy,));
if(id[sx][sy]){
dist[num][id[sx][sy]]=;
if(++cnt==k) return ;
}
while(q.size()){
M now=q.front();q.pop();
for(int i=,nx,ny;i<=;i++){
nx=now.x+dx[i];ny=now.y+dy[i];
if(vis[nx][ny]||!inside(nx,ny)||mp[nx][ny]=='*') continue;
vis[nx][ny]=;
if(id[nx][ny]){
if(dist[num][id[nx][ny]]==inf) dist[num][id[nx][ny]]=now.step+;
if(++cnt==k) return ;
}
q.push(M(nx,ny,now.step+));
}
}
}
inline void mapping(){
memset(dist,inf,sizeof dist);
S=;T=k<<|;
for(int i=;i<=k;i++){
bfs(i);
}
for(int i=;i<=k;i++){
for(int j=;j<=k;j++){
if(dist[i][j]!=inf) add(i,j+k,,dist[i][j]);
}
}
for(int i=;i<=k;i++) add(S,i,,),add(i+k,T,,);
}
/*稠密图EK不如zkw跑的快
inline bool spfa(){
for(int i=S;i<=T;i++) mark[i]=0,dis[i]=inf;
unsigned short h=0,t=1;q[t]=S;dis[S]=0;
while(h!=t){
int x=q[++h];mark[x]=0;
for(int i=head[x];i;i=e[i].next){
if(e[i].cap&&dis[e[i].v]>dis[x]+e[i].cost){
dis[e[i].v]=dis[x]+e[i].cost;
prev[e[i].v]=i;
if(!mark[e[i].v]){
mark[e[i].v]=1;
if(dis[e[i].v]<dis[x]) q[h--]=e[i].v;
else q[++t]=e[i].v;
}
}
}
}
return dis[T]!=inf;
}
inline void augment(){
int flow=inf;
for(int i=T;i!=S;i=e[prev[i]^1].v){
flow=min(flow,e[prev[i]].cap);
}
for(int i=T;i!=S;i=e[prev[i]^1].v){
e[prev[i]].cap-=flow;
e[prev[i]^1].cap+=flow;
}
ans+=flow*dis[T];
}*/
inline bool spfa(){
for(int i=S;i<=T;i++) mark[i]=,dis[i]=inf;
int h=,t=;q[t]=T;dis[T]=;mark[T]=;
while(h!=t){
int x=q[++h];mark[x]=;
for(int i=head[x];i;i=e[i].next){
int v=e[i].v;
if(e[i^].cap&&dis[v]>dis[x]+e[i^].cost){
dis[v]=dis[x]+e[i^].cost;
if(!mark[v]){
mark[v]=;
q[++t]=v;
}
}
}
}
return dis[S]<inf;
}
int dfs(int x,int f){
mark[x]=;
if(x==T) return f;
int used=,w;
for(int i=head[x];i;i=e[i].next){
int v=e[i].v;
if(!mark[v]&&e[i].cap&&dis[v]+e[i].cost==dis[x]){
w=dfs(v,min(f-used,e[i].cap));
e[i].cap-=w;e[i^].cap+=w;
ans+=w*e[i].cost;
used+=w;
if(used==f) return used;
}
}
return used;
}
inline void zkw(){
while(spfa()){
mark[T]=;
while(mark[T]){
memset(mark,,sizeof mark);
dfs(S,inf);
}
}
}
int main(){
setfire(chess);
init();
mapping();
zkw();
//while(spfa()) augment();
printf("%d",ans);
return ;
}
//最后一个点5.39s,zkw费用流死活跑不过去

最新文章

  1. push方法的兼容性问题
  2. mysql 语句的索引和优化
  3. KNN算法与Kd树
  4. PHP实例练习--投票和租房子
  5. C++ Namespace 详解
  6. hadoop,hbase,pig安装
  7. Oracle 查看相关优化器参数
  8. typings的理解
  9. How to update FVDI Commander driver to latest V2015.6.2
  10. Android 的自定义Spinner组件实现方式
  11. script 表单验证
  12. 怎么修改placeholder字体的css样式
  13. 菜单组件——axure线框图部件库介绍
  14. Caffe安装过程错误处理方法
  15. 软件性能测试技术树(三)----数据库(MySQL)性能
  16. JNI加载hal的dlopen()相关操作
  17. Thread类(线程)
  18. tar命令-压缩,解压缩文件
  19. CentOS下安装MYSQL8.X并设置忽略大小写
  20. linux搭建C开发环境

热门文章

  1. linux 关闭ping探测
  2. Hibernate3和4版本的不同
  3. zookeeper启动错误 ---- Unable to load database on disk
  4. mysql关于访问权限以及root密码修改
  5. dubbo官网和帮助文档
  6. 联想Y430P CentOS 7.3 无线网络的配置
  7. [Other] An Overview of Arrays and Memory
  8. POJ1258 Agri-Net MST最小生成树题解
  9. 微信小程序 之 请求函数封装
  10. 【Java】Java_19递归算法