bzoj2668 [cqoi2012]交换棋子
来源:互联网 发布:翅片式换热器计算软件 编辑:程序博客网 时间:2024/05/17 23:36
【题意】
n*m棋盘,每次可以交换相邻(八连通)棋子,每个格子交换次数存在上限,求将初始棋盘置换为目标棋盘的最少交换次数。
【数据范围】
n<=20,m<=20,0<=交换次数<=9
【思路】
费用流
将每次交换看成白棋子的移动,则流量为白棋子总数,答案即最小费用,求最小费用最大流
关键在于交换次数上限问题,对于每个点,将上限适当修改后,限制的是这个点的流入量+流出量的和,因为流入量=流出量,故修改后的上限除以二即可得到该点流量限制
注意这题是八连通。。
【时间复杂度】
费用流,点数O(n^2),边数O(n^2)
#include<cstdio>#include<cstring>#include<algorithm>#define N 810#define inf 2147483647using namespace std; const int dx[8]={-1, -1, -1, 0, 0, 1, 1, 1};const int dy[8]={-1, 0, 1, -1, 1, -1, 0, 1};struct edge{int x, y, l, c, next;}a[100010];int n, m, m1[30][30], m2[30][30], m3[30][30], ans, cost, p[N], flag[N], h[N], S, T, fa[N],l, op, cl, d[N], x, sum1, sum2, xx, yy;char s[30]; void add(int x, int y, int ll, int c){ a[++l].x=x; a[l].y=y; a[l].l=ll; a[l].c=c; a[l].next=p[x]; p[x]=l; a[++l].x=y; a[l].y=x; a[l].l=0; a[l].c=-c; a[l].next=p[y]; p[y]=l;} int spfa(){ memset(flag, 0, sizeof(flag)); for(int i=0; i<=T; i++){h[i]=inf; fa[i]=0;} h[S]=0; flag[S]=1; op=0; cl=1; d[1]=S; while(op!=cl){ op++; if(op>809)op=1; int v=d[op]; for(int i=p[v]; i; i=a[i].next) if(a[i].l&&h[a[i].y]>h[v]+a[i].c){ h[a[i].y]=h[v]+a[i].c; fa[a[i].y]=i; if(!flag[a[i].y]){ flag[a[i].y]=1; cl++; if(cl>809)cl=1; d[cl]=a[i].y; } } flag[v]=0; } return fa[T]?1:0;}void dfs(){ int mn=inf; for(int i=fa[T]; i; i=fa[a[i].x])mn=min(mn, a[i].l); ans+=mn; for(int i=fa[T]; i; i=fa[a[i].x]){ cost+=mn*a[i].c; a[i].l-=mn; a[i^1].l+=mn; }} int main(){ scanf("%d%d", &n, &m); for(int i=1; i<=n; i++){ scanf("%s", s+1); for(int j=1; j<=m; j++)m1[i][j]=s[j]-'0'; } for(int i=1; i<=n; i++){ scanf("%s", s+1); for(int j=1; j<=m; j++)m2[i][j]=s[j]-'0'; } for(int i=1; i<=n; i++){ scanf("%s", s+1); for(int j=1; j<=m; j++)m3[i][j]=s[j]-'0'; } l=1; memset(p, 0, sizeof(p)); S=0; T=n*m*2+1; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++){ x=(i-1)*m+j; if(m1[i][j])add(S, x, 1, 0); if(m2[i][j])add(n*m+x, T, 1, 0); add(x, n*m+x, (m3[i][j]+m1[i][j]+m2[i][j])/2, 0); for(int k=0; k<=7; k++){ xx=i+dx[k]; yy=j+dy[k]; if(1<=xx&&xx<=n&&1<=yy&&yy<=m)add(n*m+x, (xx-1)*m+yy, inf, 1); } } sum1=sum2=0; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++){sum1+=m1[i][j]; sum2+=m2[i][j];} if(sum1!=sum2){printf("-1"); return 0;} ans=cost=0; while(spfa())dfs(); if(ans!=sum1){printf("-1"); return 0;} printf("%d", cost); return 0;}
0 0
- bzoj2668 [cqoi2012]交换棋子
- bzoj2668: [cqoi2012]交换棋子
- bzoj2668 [cqoi2012]交换棋子
- BZOJ2668: [cqoi2012]交换棋子 费用流
- 【BZOJ2668】【cqoi2012】交换棋子 费用流
- 【bzoj2668】【cqoi2012】【交换棋子】【费用流】
- CQOI2012 交换棋子
- 2668: [cqoi2012]交换棋子
- [CQOI2012]交换棋子
- 【bzoj 2668】: [cqoi2012]交换棋子
- bzoj 2668: [cqoi2012]交换棋子
- 【CQOI2012】交换棋子(费用流)
- [CQOI2012]交换棋子【网络流】【费用流】
- bzoj2668
- 棋子
- 棋子
- BZOJ 2668 CQOI 2012 交换棋子 费用流
- 【bzoj 2666】: [cqoi2012]组装
- spring基础配置
- Trie (3) -- Maximum XOR of Two Numbers in an Array
- 在tomcat下context.xml中配置各种数据库连接池
- Leetcode007-Reverse Integer
- 线性规划与网络流24——数字梯形问题
- bzoj2668 [cqoi2012]交换棋子
- Home键的广播监听
- java 并发概念与内存分析,原子性、可见性、有序性
- final修饰符
- CodeForces 136A Presents
- php类面向对象学习笔记
- Growth of a Population
- 在慕课上学习的,HTML和CSS基础学习笔记6
- javascript 学习1