费用流

这种棋盘模型大概都是网络流吧

首先我们知道棋子之间不会影响到达目标的步数,那么就好做了,枚举终点,然后就是最小权匹配了,因为就是寻找总和最小,然后费用流就行了。

#include<bits/stdc++.h>
using namespace std;
const int N = , inf = 0x3f3f3f3f;
struct data {
int x, y;
} a[N];
struct edge {
int nxt, to, f, c;
} e[N * N];
int n, S, T, tot, cnt = , ans, kase;
int head[N], dis[N], q[N], Map[N][N], pree[N], prevv[N], inq[N];
void link(int u, int v, int f, int c)
{
e[++cnt].nxt = head[u];
head[u] = cnt;
e[cnt].to = v;
e[cnt].f = f;
e[cnt].c = c;
}
void insert(int u, int v, int f, int c)
{
link(u, v, f, c);
link(v, u, , -c);
}
bool spfa()
{
int l = , r = ;
memset(dis, 0x3f3f, sizeof(dis));
dis[] = ;
q[++r] = ;
while(l <= r)
{
int u = q[l++];
inq[u] = ;
for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && dis[e[i].to] > dis[u] + e[i].c)
{
pree[e[i].to] = i;
prevv[e[i].to] = u;
dis[e[i].to] = dis[u] + e[i].c;
if(!inq[e[i].to])
{
inq[e[i].to] = ;
q[++r] = e[i].to;
}
}
}
return dis[T] != 0x3f3f3f3f;
}
int getflow()
{
int now = T, delta = inf;
while(now)
{
delta = min(delta, e[pree[now]].f);
now = prevv[now];
}
now = T;
while(now)
{
e[pree[now]].f -= delta;
e[pree[now] ^ ].f += delta;
now = prevv[now];
}
return delta * dis[T];
}
int maxcostflow()
{
int ret = ;
while(spfa()) ret += getflow();
return ret;
}
void build()
{
memset(head, , sizeof(head));
cnt = ;
for(int i = ; i <= n; ++i) insert(S, i, , );
for(int i = ; i <= n; ++i)
for(int x = ; x <= n; ++x)
for(int y = ; y <= n; ++y) if(Map[x][y])
insert(i, Map[x][y], , abs(a[i].x - x) + abs(a[i].y - y));
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j) if(Map[i][j])
insert(Map[i][j], T, , );
}
int main()
{
while(scanf("%d", &n))
{
if(!n) break;
T = * n + ;
ans = inf;
for(int i = ; i <= n; ++i) scanf("%d%d", &a[i].x, &a[i].y);
for(int i = ; i <= n; ++i)
{
memset(Map, , sizeof(Map));
tot = n;
for(int j = ; j <= n; ++j) Map[i][j] = ++tot;
build();
ans = min(ans, maxcostflow());
memset(Map, , sizeof(Map));
tot = n;
for(int j = ; j <= n; ++j) Map[j][i] = ++tot;
build();
ans = min(ans, maxcostflow());
}
memset(Map, , sizeof(Map));
tot = n;
for(int i = ; i <= n; ++i) Map[i][i] = ++tot;
build();
ans = min(ans, maxcostflow());
memset(Map, , sizeof(Map));
tot = n;
for(int i = ; i <= n; ++i) Map[i][n - i + ] = ++tot;
build();
ans = min(ans, maxcostflow());
printf("Board %d: %d moves required.\n\n", ++kase, ans);
}
return ;
}

LA3276的更多相关文章

随机推荐

  1. 3星|《刷新》:微软第三任CEO上任三年后的回顾

    刷新:重新发现商业与未来 作者是微软第三任CEO,2014年2月上任.本书英文版出版于2017年9月,全书内容大致截至于2017年年初,算是作者上任三年后的回顾. 书中作者讲了不少自己的个人经历.作者 ...

  2. 《C++ Primer 第5版》第1章

    1.1 一个简单的C++程序 #include <iostream>int main() {    std::cout << "Hello World!" ...

  3. 阅读《JavaScript设计模式》第二章心得

    面向对象编程 面向对象编程就是将你的需求抽象成一个对象.然后针对这个对象分析其特征(属性)与动作(方法).这个对象我们称之为类.面向对象编程思想其中的一个特点就是封装. 1.私有属性.私有方法.特权方 ...

  4. HDU 1465(错排公式)

    不容易系列之一 题意: 一个人要寄n个信封,结果装错了.信纸的编号为1到n,信封的编号为1到n,信纸的编号不能和信封的编号一样,全都不能一样. 思路:错排公式. D(n)表示n件信封装错的所有的情况. ...

  5. 【模板】dijkstra

    洛谷 4779 #include<cstdio> #include<cstring> #include<algorithm> #include<queue&g ...

  6. (40). springboot + devtools(热部署)【从零开始学Spring Boot】

    我们之前在在()Spring Boot热部署[从零开始学Spring Boot] (http://412887952-qq-com.iteye.com/blog/2291518 )讲过通过使用spri ...

  7. 清北学堂模拟赛d6t2 刀塔

    分析:看到最小值最大就很显然是二分了吧,二分一下最小值,把小于它的数给删掉,然后看每个数向左边能延伸多长,往右边能延伸多长,最后统计一下有没有可行答案就可以了. #include <cstdio ...

  8. nyoj_114_某种序列_201403161700

    某种序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 数列A满足An = An-1 + An-2 + An-3, n >= 3 编写程序,给定A0, A1 ...

  9. 【ACM】hdu_zs3_1007_Rails_201308100802

    Rails Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other)Total Submissi ...

  10. POJ 3061 Subsequence 尺取

    Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14698   Accepted: 6205 Desc ...