交换棋子题解

本文介绍了P3159 [CQOI2012]交换棋子的题解,主要通过费用流的方法解决。在将白棋视为空白区域后,将黑色棋子的移动转化为流量问题,每个棋子的移动受限,用费用流来计算最小成本。文章讨论了不拆点、拆两点和拆三点的策略,其中拆三点的方法更易理解,通过设置不同点的流量和花费,求解最小花费路径。
摘要由CSDN通过智能技术生成

P3159 [CQOI2012]交换棋子

题意
在这里插入图片描述

把这题作为费用流入门题真的会自闭

有误请指出,谢谢~
正解: 首先可以把白棋当作空白区域,从起始位置到最终位置可以看成是若干黑色棋子的移动,并且每个格子有访问次数限制。可以把限制作为流量,每次的交换形似花费,这时候就能想到要用费用流了
在这里插入图片描述

首先考虑不拆点的做法,把棋盘每相邻的两个建立一条边,但是这样的话每个格子的访问次数限制就没法体现了,没有办法统计从四面八方经过的黑色棋子。
在这里插入图片描述

这时候考虑拆成两个点的做法。可以想到,除了起点和终点每次经过是访问一次,路径上的点访问次数都是两次。这样做确实也没问题,就是把每个点的流量设置为每个格子的限制,黑棋的起点和终点花费设置为1,其他的点设为2。
在这里插入图片描述

更好理解的做法是拆成三个点,访问次数限制转化为流量的时候三个点中的两条边均摊流量,花费是0,针对连到两个格子间的边流量设为无穷大,花费为1,最后算在这样的流量限制下能跑到的最小花费。具体细节看代码:

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define PI acos(-1)
#define eps 1e-8
#define rint register int
#define oo 1e5
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<double, int> pdi;
typedef pair<LL, LL> pll;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
   
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') {
    if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int ne[8][2] = {
   1, 0, -1, 0, 0, 1, 0, -1, -1, -1, -1, 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值