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

  事实上,可以忽略此条件,因为棋子是相同的,我们可以用合法的等效方案替代一棋子越过另一棋子的情况: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费用流死活跑不过去

SDOI2012 Round1 day2 象棋(chess)解题报告的更多相关文章

  1. SDOI2012 Round1 day2 拯救小云公主(dis)解题报告

    #include<cstdio> #include<cmath> #include<iostream> using namespace std; typedef l ...

  2. SDOI2012 Round1 day2 集合(set)解题报告

    //=====================以上为官方题解==============// 数据略水,暴力枚举50. 把边按照升序排一遍,在询问,水过. #include<cstdio> ...

  3. 洛谷 P4363 [九省联考2018]一双木棋chess 解题报告

    P4363 [九省联考2018]一双木棋chess 题目描述 菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落 ...

  4. 洛谷 P2498 [SDOI2012]拯救小云公主 解题报告

    P2498 [SDOI2012]拯救小云公主 题目描述 英雄又即将踏上拯救公主的道路-- 这次的拯救目标是--爱和正义的小云公主. 英雄来到\(boss\)的洞穴门口,他一下子就懵了,因为面前不只是一 ...

  5. 雅礼集训 Day2 T3 联盟 解题报告

    联盟 题目描述 \(\text{G}\) 国周边的 \(n\) 个小国家构成一个联盟以抵御 \(\text{G}\) 国入侵, 为互相支援,他们建立了\(n−1\) 条双向通路, 使得任意两个国家可以 ...

  6. noip2013 Day2 T2 花匠 解题报告

    题目: 3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大, ...

  7. 【百度之星2014~初赛(第二轮)解题报告】Chess

    声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载.可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...

  8. GX/GZOI2019 day2 解题报告

    GX/GZOI2019 day2 解题报告 题目链接 逼死强迫症 旅行者 旧词 t1 逼死强迫症 显然地,记 \(f(i)\) 为长度为 \(i\) 的木板的答案,可得: \(\\\) \[f(i)= ...

  9. 【NOIP2015】提高day2解题报告

    题目: P1981跳石头 描述 一年一度的“跳石头”比赛又要开始了!这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N ...

随机推荐

  1. ISP基础一

    1.专业术语 [ColorTemp] 色温 所谓色温,简而言之,就是定量地以开尔文温度(K)来表示色彩.英国著名物理学家开尔文认为,假定某一黑体物质,能够将落在其上的所有热量吸收,而没有损失,同时又能 ...

  2. org.apache.hadoop.ipc.RemoteException: User: root is not allowed to impersonate root

    修改 core-site.xml文件 vim /usr/local/hadoop/etc/hadoop/core-site.xml 增加: <property> <name>h ...

  3. python读写文件write和flush

    打开文件用open,该函数创建一个文件对象,这将用来调用与之关联的其他支持方式. file object = open(file_name [, access_mode][, buffering]) ...

  4. [转载]CentOS 6.5 安装五笔输入法

    FROM:http://blog.sina.com.cn/s/blog_49d6d41c0101i0zs.html 1.一般安装了中文环境会默认安装了好多输入法,先删除了ibus  sudo yum ...

  5. 2017.6.29 java读取.properties配置文件的几种方法

    参考来自:http://www.cnblogs.com/s3189454231s/p/5626557.html 关于路径的解释:http://blog.csdn.net/bluishglc/artic ...

  6. ZOJ1157, POJ1087,UVA 753 A Plug for UNIX (最大流)

    链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action? id=26746 题目意思有点儿难描写叙述 用一个别人描写叙述好的. 我的 ...

  7. www.mentalis.org/

    Top Downloads Here are the top downloads (within the last 24 hours): 1. Proxy2. IniReader3. ProxySoc ...

  8. mysql double 乘法 缺失精度

    CREATE TABLE tmp_decimal( id BIGINT auto_increment PRIMARY KEY , amount DOUBLE ); 创建测试表 插入测试数据 INSER ...

  9. ubuntu apt-get install xxx时一直报错E: Unable to locate package xxxxxxx

    $ sudo add-apt-repository main $ sudo add-apt-repository universe $ sudo add-apt-repository restrict ...

  10. mother&#39;s day.py 母亲节

    今天母亲节,写了个程序.抓取一个站点的母亲节祝福短信.实现自己主动翻页, 道友们也能够甲乙改造.比方加上节日简洁,time()模块. . . 一起分享吧 # -*- coding: cp936 -*- ...