狼抓兔子(HYSBZ-1001)
Problem Description
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
- (x,y)<==>(x+1,y)
- (x,y)<==>(x,y+1)
- (x,y)<==>(x+1,y+1)
道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10MOutput
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6Sample Output
14
思路:
将起点最下方的点与终点最上方的点相连,画一条射线,将平面分成左下和右上两个部分,分别定义为 S、T,这样一条从 S 到 T 的路径就将图的起点和终点隔开,然后求其最小割即可
由于图给的是平面图,那么可以将图转换为对偶图,跑最短路算法即可
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
const int MOD = 1E9+7;
const int N = 2000000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;
int n,m,num;
struct data {
int to,next;
int dis;
} edge[4*N];
int head[N],tot;
int dis[N],Q[N];
bool vis[N];
void addEdge(int x,int y,int dis) {
tot++;
edge[tot].to=y;
edge[tot].dis=dis;
edge[tot].next=head[x];
head[x]=tot;
}
void SPFA() {
memset(dis,INF,sizeof(dis));
int tail=0,first=1;
dis[0]=Q[first]=0;
vis[0]=true;
while(tail!=first) {
int x=Q[tail++];
if(tail==N)
tail=0;
vis[x]=false;
for(int i=head[x]; i!=-1; i=edge[i].next) {
int y=edge[i].to;
if(dis[y]>dis[x]+edge[i].dis) {
dis[y]=dis[x]+edge[i].dis;
if(vis[y]==0) {
vis[y]=true;
Q[first++]=y;
if(first==N)
first=0;
}
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
num=(n*m-m-n+1)*2+1;
memset(head,-1,sizeof(head));
for(int i=1; i<m; i++) {
int x;
scanf("%d",&x);
addEdge(i,num,x);
addEdge(num,i,x);
}
for(int i=1; i<n-1; i++) {
for(int j=1; j<m; j++) {
int x;
scanf("%d",&x);
addEdge((i*2)*(m-1)+j,((i*2)-1)*(m-1)+j,x);
addEdge(((i*2)-1)*(m-1)+j,(i*2)*(m-1)+j,x);
}
}
for(int i=1; i<m; i++) {
int x;
scanf("%d",&x);
addEdge(0,((n*2)-3)*(m-1)+i,x);
addEdge(((n*2)-3)*(m-1)+i,0,x);
}
for(int i=0; i<n-1; i++) {
for(int j=1; j<=m; j++) {
int x;
scanf("%d",&x);
if(j==1){
addEdge(0,(i*2)*(m-1)+m,x);
addEdge((i*2)*(m-1)+m,0,x);
}
else if(j==m){
if((i*2)%2){
addEdge((i*2)*(m-1),num,x);
addEdge(num,(i*2)*(m-1),x);
}
else{
addEdge((i*2+1)*(m-1),num,x);
addEdge(num,(i*2+1)*(m-1),x);
}
}
else {
addEdge((i*2)*(m-1)+j-1,(i*2)*(m-1)+j+m-1,x);
addEdge((i*2)*(m-1)+j+m-1,(i*2)*(m-1)+j-1,x);
}
}
}
for(int i=0; i<n-1; i++) {
for(int j=1; j<m; j++) {
int x;
scanf("%d",&x);
if((i*2)%2){
addEdge((i*2)*(m-1)+j,(i*2)*(m-1)+j,x);
addEdge((i*2)*(m-1)+j,(i*2)*(m-1)+j,x);
}
else{
addEdge((i*2+1)*(m-1)+j,(i*2)*(m-1)+j,x);
addEdge((i*2)*(m-1)+j,(i*2+1)*(m-1)+j,x);
}
}
}
SPFA();
printf("%d",dis[num]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!