BZOJ1001: [BeiJing2006]狼抓兔子

探讨了一个关于狼抓兔子的趣味算法问题,利用最短路径算法解决狼如何以最少数量伏击兔子,确保所有兔子被捕获。文章详细介绍了问题背景、输入输出格式、样例,并提供了一个具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

1001: [BeiJing2006]狼抓兔子

题目

Description

现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,

而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

img

左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路

1:(x,y)<==>(x+1,y)

2:(x,y)<==>(x,y+1)

3:(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个数,表示斜向道路的权值.

输入文件保证不超过10M

Output

输出一个整数,表示参与伏击的狼的最小数量.

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 6

Sample Output

14

HINT

2015.4.16新加数据一组,可能会卡掉从前可以过的程序。

Source


妙哉

但是有点坑(如果仔细一点还是想得到)

这道题可以直接最短路,具体说来:

按照从左下到右上的直线将图分层(斜线连接的层数相差2,横线竖线连接的层相差1),那么兔子要被吃掉当且仅当在从这一层到另外一层的时候。

于是我么需要证明一个东西:

狼的路线是首尾相连的,即狼形成了一条链,区别于多叉树以及根节点数量大于1的森林(环就不说了,下面会给出证明)

证明:显然可得法,一波带走。(鸽掉了)

于是直接从左下的超级起点向右上的超级终点最短路就可以了。

注意:当 n = = 1 n==1 n==1 m = = 1 m==1 m==1的时候一定要特判
蒟蒻我WA飞了

顺便说一下,我的点是按照这种方式弄的。

avator
我没有鸽掉,只是图床鸽掉了

C o d e : Code: Code:

#include <bits/stdc++.h>
#define ENDL printf ("\n")
#ifdef wll
#include <windows.h>
#endif
#define xx first
#define yy second

using namespace std;

struct _in {
    const _in&operator , (register int & a) const {
        a = 0;
        char k = getchar ();
        int f = 1;
        while (k <'0' || k > '9') {
            if (k == '-') {
                f = -1;
            }
            k = getchar ();
        }
        while (k <= '9' && k >= '0') {
            a = a * 10 + k - '0';
            k = getchar ();
        }
        a *= f;
        return *this;
    }
}in;

const int N = 1000 + 5, M = 3000500 + 5, maxn = 1000100;
//int fr[M << 1 | 1], to[M << 1 | 1], h[N * N * 2], w[M << 1 | 1], tot;
int fr[maxn << 3], to[maxn << 3], h[maxn << 3], w[maxn << 3], tot;
inline void add (int u, int v, int val) {
//	printf ("%d %d %d\n", u, v, val);
	tot++;
	fr[tot] = h[u];
	to[tot] = v;
	h[u] = tot;
	w[tot] = val;
}
int n, m, s, t;
int dis[maxn << 3];
bool inq[maxn << 3];
queue <int> Q;
inline int Pos (int u, int v) {
	return (u - 1) * (m - 1) + v;
}

int main () {
    #ifdef wll
    freopen ("testdata.in", "r", stdin);
//	freopen ("data.out", "w", stdout);
    #endif
    scanf ("%d%d", &n, &m);
    int tmin = INT_MAX;
    s = 2 * (n - 1) * (m - 1) + 1;
    t = s + 1;
    for (int i = 1; i <= n; ++i) {
    	for (int j = 1; j <= m - 1; ++j) {
    		int tmp;
    		scanf ("%d", &tmp);
    		tmin = min (tmin, tmp);
    		if (i == 1) {
    			add (Pos (1, j), t, tmp);
    			add (t, Pos (1, j), tmp);
				}
				else if (i == n) {
					add (s, Pos (2 * n - 2, j), tmp);
					add (Pos (2 * n - 2, j), s, tmp);
				}
				else {
					add (2 * (i - 1) * (m - 1) + j - (m - 1), 2 * (i - 1) * (m - 1) + j, tmp);
					add (2 * (i - 1) * (m - 1) + j, 2 * (i - 1) * (m - 1) + j - (m - 1), tmp);
				}
			}
		}
		for (int i = 1; i <= n - 1; ++i) {
			for (int j = 1; j <= m; ++j) {
				int tmp;
				scanf ("%d", &tmp);
				tmin = min (tmin, tmp);
				if (j == 1) {
					add (s, Pos (i * 2, j), tmp);
					add (Pos (i * 2, j), s, tmp);
				}
				else if(j == m) {
					add (Pos (i * 2 - 1, m - 1), t, tmp);
					add (t, Pos (i * 2 - 1, m - 1), tmp);
				}
				else {
					add (Pos (i * 2 - 1, j - 1), Pos (i * 2, j), tmp);
					add (Pos (i * 2, j), Pos (i * 2 - 1, j - 1), tmp);
				}
			}
		}
		for (int i = 1; i <= n - 1; ++i) {
			for (int j = 1; j <= m - 1; ++j) {
				int tmp;
				scanf ("%d", &tmp);
				add (Pos (i * 2 - 1, j), Pos (i * 2, j), tmp);
				add (Pos (i * 2, j), Pos (i * 2 - 1, j), tmp);
			}
		}
		if (n == 1 || m == 1) {
			printf ("%d\n", tmin);
			return 0;
		}
		memset (dis, 127, sizeof (dis));
		Q.push (s);
		inq[s] = 1;
		dis[s] = 0;
		while (Q.size ()) {
			int tmp = Q.front ();
			Q.pop ();
			inq[tmp] = 0;
			for (int i = h[tmp]; i; i = fr[i]) {
				if (dis[to[i]] > dis[tmp] + w[i]) {
					dis[to[i]] = dis[tmp] + w[i];
					if(!inq[to[i]]) {
						inq[to[i]] = 1;
						Q.push (to[i]);
					} 
				}
			}
		}
		printf ("%d\n", dis[t]);
    return 0;
}
内容概要:本文深入解析了扣子COZE AI编程及其详细应用代码案例,旨在帮助读者理解新一代低门槛智能体开发范式。文章从五个维度展开:关键概念、核心技巧、典型应用场景、详细代码案例分析以及未来发展趋势。首先介绍了扣子COZE的核心概念,如Bot、Workflow、Plugin、Memory和Knowledge。接着分享了意图识别、函数调用链、动态Prompt、渐进式发布及监控可观测等核心技巧。然后列举了企业内部智能客服、电商导购助手、教育领域AI助教和金融行业合规质检等应用场景。后,通过构建“会议纪要智能助手”的详细代码案例,展示了从需求描述、技术方案、Workflow节点拆解到调试与上线的全过程,并展望了多智能体协作、本地私有部署、Agent2Agent协议、边缘计算插件和实时RAG等未来发展方向。; 适合人群:对AI编程感兴趣的开发者,尤其是希望快速落地AI产品的技术人员。; 使用场景及目标:①学习如何使用扣子COZE构建生产级智能体;②掌握智能体实例、自动化流程、扩展能力和知识库的使用方法;③通过实际案例理解如何实现会议纪要智能助手的功能,包括触发器设置、下载节点、LLM节点Prompt设计、Code节点处理和邮件节点配置。; 阅读建议:本文不仅提供了理论知识,还包含了详细的代码案例,建议读者结合实际业务需求进行实践,逐步掌握扣子COZE的各项功能,并关注其未来的发展趋势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值