【HackerRank】Jumping Rooks(最小费用最大流)
2016-09-07 17:29
447 查看
【HackerRank】Jumping Rooks(最小费用最大流)
题目大意:
一个n*n的地图,’#’为山峰,’.’为可用位置。
要放置k个士兵在’.’上,已知每个士兵会攻击同行和同列中能看到的士兵。
即两个士兵如果在同行或同列,且其最短距离内没有’#’,两个士兵为一对可互相攻击的士兵。
问怎样放置k个士兵,才能让可互相攻击的士兵对数最少,输出最少的互相攻击对数。
网络流阿网络流 最小费阿最小费 没想到阿没想到 好神奇阿好神奇……
不太好想,想到了真心感觉好神奇……
首先’#’会把原图分为好几段横块和好几段竖块。给每个块标号,同时记录每个点所在的横块标号和竖块标号。当然’#’不会被算做一块。
设置一个虚源点和虚汇点。
源点与所有横块相连,连n+1条边,每条边流量为1,花费分别为0~n。
所有竖块连到汇点,连n+1条边,每条边流量为1,花费分别为0~n。
遍历图中每一个点,’#’则跳过,对于’.’的点(i,j),所在横块和竖块连接一条边,流量1,费用0。这样图就建好了。
跑法的话,k次最小费,因为保证k <= 可用点数量,所以每次肯定能跑出来一条路。流量肯定是1。此外,这条路一定是源点->横块->竖块->汇点这种模式,其实也就是对应放置了一个士兵。
源点->横块的费用其实就是该横块已有的士兵数,因为源点到该横块的边是费用递增的,保证最小费的话,当前如果是第i小费用的边,该士兵肯定是该横块上第i个士兵,一样的,攻击到的兵数为i-1,也就是该边的费用了。
对于竖块->汇点一样的。
同时图上每个点(i,j)仅对应一条横块到竖块的点,那么就保证了每个点最多放一个士兵。
代码如下:
题目大意:
一个n*n的地图,’#’为山峰,’.’为可用位置。
要放置k个士兵在’.’上,已知每个士兵会攻击同行和同列中能看到的士兵。
即两个士兵如果在同行或同列,且其最短距离内没有’#’,两个士兵为一对可互相攻击的士兵。
问怎样放置k个士兵,才能让可互相攻击的士兵对数最少,输出最少的互相攻击对数。
网络流阿网络流 最小费阿最小费 没想到阿没想到 好神奇阿好神奇……
不太好想,想到了真心感觉好神奇……
首先’#’会把原图分为好几段横块和好几段竖块。给每个块标号,同时记录每个点所在的横块标号和竖块标号。当然’#’不会被算做一块。
设置一个虚源点和虚汇点。
源点与所有横块相连,连n+1条边,每条边流量为1,花费分别为0~n。
所有竖块连到汇点,连n+1条边,每条边流量为1,花费分别为0~n。
遍历图中每一个点,’#’则跳过,对于’.’的点(i,j),所在横块和竖块连接一条边,流量1,费用0。这样图就建好了。
跑法的话,k次最小费,因为保证k <= 可用点数量,所以每次肯定能跑出来一条路。流量肯定是1。此外,这条路一定是源点->横块->竖块->汇点这种模式,其实也就是对应放置了一个士兵。
源点->横块的费用其实就是该横块已有的士兵数,因为源点到该横块的边是费用递增的,保证最小费的话,当前如果是第i小费用的边,该士兵肯定是该横块上第i个士兵,一样的,攻击到的兵数为i-1,也就是该边的费用了。
对于竖块->汇点一样的。
同时图上每个点(i,j)仅对应一条横块到竖块的点,那么就保证了每个点最多放一个士兵。
代码如下:
#include <iostream> #include <cmath> #include <vector> #include <cstdlib> #include <cstdio> #include <climits> #include <ctime> #include <cstring> #include <queue> #include <stack> #include <list> #include <algorithm> #include <map> #include <set> #define LL long long #define Pr pair<int,int> #define fread(ch) freopen(ch,"r",stdin) #define fwrite(ch) freopen(ch,"w",stdout) using namespace std; const int INF = 0x3f3f3f3f; const int mod = 1e9+7; const double eps = 1e-8; const int MAXK = 5511; const int MAXM = 6255555; struct Edge { int v,cap,cost,next; Edge(){} Edge(int _v,int _cap,int _cost,int _next):v(_v),cap(_cap),cost(_cost),next(_next){} }; Edge eg[MAXM]; char mp[55][55]; int head[MAXK]; int R[55][55],C[55][55]; int tp,s,t; int pre[MAXK]; int dis[MAXK]; bool vis[MAXK]; void Add(int u,int v,int cap,int cost) { eg[tp] = Edge(v,cap,cost,head[u]); head[u] = tp++; eg[tp] = Edge(u,0,-cost,head[v]); head[v] = tp++; } int spfa() { memset(vis,0,sizeof(vis)); memset(dis,INF,sizeof(dis)); memset(pre,-1,sizeof(pre)); queue <int> q; q.push(s); dis[s] = 0; int u,v,w,c; while(!q.empty()) { u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; i != -1; i = eg[i].next) { v = eg[i].v; c = eg[i].cost; if(eg[i].cap && dis[u]+c < dis[v]) { dis[v] = dis[u]+c; pre[v] = i; if(!vis[v]) { vis[v] = 1; q.push(v); } } } } u = t; while(u != s) { eg[pre[u]].cap--; eg[pre[u]^1].cap++; u = eg[pre[u]^1].v; } return dis[t]; } int main() { //fread(""); //fwrite(""); int n,k; scanf("%d%d",&n,&k); for(int i = 0; i < n; ++i) scanf("%s",mp[i]); memset(head,-1,sizeof(head)); tp = 0; int id = 0; //给横块标号 for(int i = 0; i < n; ++i) { int j = 0; while(j < n) { if(mp[i][j] == '#') ++j; else { id++; while(j < n && mp[i][j] != '#') R[i][j++] = id; } } } int cntr = id; //给竖块标号 for(int j = 0; j < n; ++j) { int i = 0; while(i < n) { if(mp[i][j] == '#') ++i; else { id++; while(i < n && mp[i][j] != '#') C[i++][j] = id; } } } s = 0; t = id+1; //源点与横块 n+1条边 for(int i = 1; i <= cntr; ++i) for(int j = 0; j <= n; ++j) Add(0,i,1,j); //竖块与汇点 n+1条边 for(int i = cntr+1; i <= id; ++i) for(int j = 0; j <= n; ++j) Add(i,t,1,j); //每个可放位置对应的边 横块->竖块 for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) { if(mp[i][j] == '#') continue; Add(R[i][j],C[i][j],1,0); } int ans = 0; //k条路(k个士兵) while(k--) ans += spfa(); printf("%d\n",ans); return 0; }
相关文章推荐
- [JZOJ5126]棋盘/[HackerRank-HourRank12]Jumping Rooks
- HackerRank "Stone Division, Revisited"
- HackerRank "Lena Sort"
- 【公式推导+杨辉三角+异或性质+进制表示】XOR Matrix HackerRank - xor-matrix
- [HackerRank]Choosing White Balls
- 【HackerRank】Utopian tree
- [hackerrank]Palindrome Index
- hackerrank_Permutation game
- HackerRank - The Maximum Subarray
- Hackerrank - Similar Pair 与线段树解法
- HackerRank# Bricks Game
- HackerRank - "Two arrays"
- HackerRank String
- HackerRank - "Sam and sub"
- HackerRank "Minimum Average Waiting Time" !
- HackerRank "Kundu and Tree" !!
- HackerRank "Minimum Penalty Path"
- [Hackerrank] The Coin Change Problem
- HackerRank Service Lane
- HackerRank "Equal Stacks"