1. 程式人生 > 實用技巧 >HDU2732 Leapin Lizards(拆點+網路流)

HDU2732 Leapin Lizards(拆點+網路流)

您的流浪蜥蜴排進入您正在探索的迷宮中的一個陌生房間。當您到處尋找隱藏的寶藏時,其中一個菜鳥踩在一塊看起來純真的石頭上,房間的地板突然消失了!排中的每隻蜥蜴都站在看似脆弱的柱子上,下面開始有熊熊大火...不要留下任何蜥蜴!儘可能多地把蜥蜴帶出房間,並報告傷亡人數。
房間中的支柱排列成網格,每個支柱與支柱的東,西,北和南相距一個單位。網格邊緣的支柱與房間的邊緣相距一個單位(安全)。並非所有支柱都一定有蜥蜴。蜥蜴可以跳到其當前d個單位內的任何空置支柱。站在房間邊緣跳躍距離內的一根柱子上的蜥蜴可能總是會跳到安全的地方...但是有一個陷阱:每個柱子在每次跳躍後都會變弱,並且很快會塌陷,不再可被其他蜥蜴使用。跳到支柱上不會導致其變弱或塌陷。只是從中跳出來,會使其減弱並最終崩潰。在任何給定時間,只有一隻蜥蜴在支柱上。
輸入值
輸入檔案將以包含一個表示測試用例數量的單個整數的行開始,最多為25。每個測試用例將從包含一個表示對映中的行數的單個正整數n的行開始,然後是一個非負整數d,代表蜥蜴的最大跳躍距離。接下來是兩張地圖,每張地圖都是字元地圖,每行一行。第一張地圖的每個位置都將包含一個數字(0-3),代表該位置的支柱在塌陷之前將持續的跳動次數(0表示那裡沒有支柱)。接下來是第二張地圖,在蜥蜴在支柱上的每個位置都帶有一個“ L”,並帶有一個“。”。每個空的支柱。沒有柱子的位置上永遠不會有蜥蜴。每個輸入圖都保證是一個大小為n x m的矩形,其中1≤n≤20和1≤m≤20。跳躍距離為
總是1≤d≤3。
輸出量
對於每種輸入情況,請列印一行,其中包含無法逃脫的蜥蜴數量。該格式應遵循以下提供的示例。

真的是很常見的套路了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
const int inf=1e9;
struct node {
    int u,v,w,nxt;
}edge[maxn<<1];
int head[maxn],tot;
void addedge (int u,int v,int w) {
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].nxt=head[u];
    head[u]
=tot++; edge[tot].u=v; edge[tot].v=u; edge[tot].w=0; edge[tot].nxt=head[v]; head[v]=tot++; } int dep[maxn],inq[maxn],cur[maxn],wjm,maxflow,s,t; bool bfs () { for (int i=0;i<=t;i++) { cur[i]=head[i]; dep[i]=inf; inq[i]=0; } dep[s]=0; queue
<int> q; q.push(s); while (q.size()) { int u=q.front(); q.pop(); inq[u]=0; for (int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inq[v]==0) { q.push(v); inq[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } int dfs (int u,int flow) { int increase=0; if (u==t) { wjm=1; maxflow+=flow; return flow; } int used=0; for (int i=cur[u];i!=-1;i=edge[i].nxt) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } int Dinic () { while (bfs()) { wjm=1; while (wjm==1) { wjm=0; dfs(s,inf); } } return maxflow; } string ss[maxn]; int a[1010][1010];//表示石柱矩陣 double getDis (int A,int B,int C,int D) { return sqrt((A-C)*(A-C)+(B-D)*(B-D)); } int n,m,d; int main () { int _; scanf("%d",&_); for (int ca=1;ca<=_;ca++) { scanf("%d%d",&n,&d); // 0為源點 // 1~n*m為上點 // n*m+1~n*m*2為下點 // n*m*2+1為匯點 // 源點向每個蜥蜴點的上點連容量為1的邊,表示只有一隻蜥蜴 // 每個點的上點向下點連一條容量為石柱高度的邊 // 每個點的下點向周圍距離d以內的上點連一條容量為inf的邊 // 每個在邊緣的點的下點向匯點連一條容量為inf的邊 for (int i=0;i<n;i++) cin>>ss[i]; m=ss[0].size(); s=0;t=n*m*2+1; for (int i=0;i<=t;i++) head[i]=-1;tot=0;maxflow=0;wjm=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[i][j]=ss[i-1][j-1]-'0'; for (int i=0;i<n;i++) cin>>ss[i]; int sum=0; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { if (ss[i-1][j-1]=='L') addedge(s,(i-1)*m+j,1),sum++; addedge((i-1)*m+j,(i-1)*m+j+n*m,a[i][j]); for (int k=1;k<=n;k++) { for (int q=1;q<=m;q++) { if (getDis(i,j,k,q)<=d) addedge((i-1)*m+j+n*m,(k-1)*m+q,inf); } } if (i<=d||n-i<d||j<=d||m-j<d) addedge((i-1)*m+j+n*m,t,inf); } } printf("Case #%d: ",ca); int ans=sum-Dinic(); if (ans==0) printf("no lizard was left behind.\n"); else if (ans==1) printf("1 lizard was left behind.\n"); else printf("%d lizards were left behind.\n",ans); } }