ZJOI2009狼和羊的故事

题目描述

狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。

输入输出格式

输入格式:

文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。

输出格式:

文件中仅包含一个整数ans,代表篱笆的最短长度。

输入样例#1:

2 2 2 2 1 1

输出样例#1:

2

解析:

      狼和羊被分开等于说任意狼和羊不连通,容易想到最小割。把狼和羊(1和2)分成两部分,源点向1连边,2向汇点连边,容量inf;1和2交界处连边,然后0向四周连边(因为0周围可任意切割),1向相邻的2连边,容量为1。然后Dinic或者ISAP。

以下是我的代码(依然比较宽。。):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #define S (n * m + 1)
  5 #define T (n * m + 2)
  6 #define ID(x, y) ((x) * m + (y))
  7 #define INF 0x7f7f7f7f
  8 using namespace std;
  9 
 10 const int dx[] = {0, 0, 1, -1};
 11 const int dy[] = {-1, 1, 0, 0};
 12 
 13 struct Edge
 14 {
 15 	int v, next, cap;
 16 	Edge(int a = 0, int b = 0, int c = 0)
 17 	:v(a), next(b), cap(c){};
 18 }edge[100020];
 19 int n, m, cnt;
 20 int head[10010], cur[10010], dep[10010], map[10010];
 21 
 22 void AddEdge(int _u, int _v, int _c)
 23 {
 24 	edge[cnt] = Edge(_v, head[_u], _c);
 25 	head[_u] = cnt++;
 26 	edge[cnt] = Edge(_u, head[_v], 0);
 27 	head[_v] = cnt++;
 28 }
 29 bool bfs()
 30 {
 31 	int queue[10010], qHead = 0, qTail = 0;
 32 	queue[qTail++] = S;
 33 	memset(dep, 0, sizeof(dep));
 34 	dep[S] = 1;
 35 	while(qTail > qHead)
 36 	{
 37 		int p = queue[qHead++];
 38 		for(int i = head[p]; ~i; i = edge[i].next)
 39 			if(edge[i].cap && !dep[edge[i].v])
 40 			{
 41 				dep[edge[i].v] = dep[p] + 1;
 42 				queue[qTail++] = edge[i].v;
 43 			}
 44 	}
 45 	return dep[T];
 46 }
 47 bool dfs(int now)
 48 {
 49 	if(now == T) return true;
 50 	for(int &i = cur[now]; ~i; i = edge[i].next)
 51 		if(edge[i].cap && dep[edge[i].v] == dep[now] + 1 && dfs(edge[i].v))
 52 		{
 53 			edge[i].cap--, edge[i ^ 1].cap++;
 54 			return true;
 55 		}
 56 	return false;
 57 }
 58 int Dinic()
 59 {
 60 	int res = 0;
 61 	while(bfs())
 62 	{
 63 		memcpy(cur, head, sizeof(head));
 64 		while(dfs(S))
 65 			res++;
 66 	}
 67 	return res;
 68 }
 69 int main()
 70 {
 71 	memset(head, -1, sizeof(head));
 72 	scanf("%d%d", &n, &m);
 73 	for(int i = 0; i < n; i++)
 74 		for(int j = 0; j < m; j++)
 75 			scanf("%d", &map[ID(i, j)]);
 76 	for(int i = 0; i < n; i++)
 77 		for(int j = 0; j < m; j++)
 78 			switch(map[ID(i, j)])
 79 			{
 80 				case 1:
 81 					AddEdge(S, ID(i, j), INF);
 82 					for(int k = 0; k < 4; k++)
 83 						if(i + dx[k] < n && i + dx[k] >= 0
 84 						&& j + dy[k] < m && j + dy[k] >= 0
 85 						&& map[ID(i + dx[k], j + dy[k])] != 1)
 86 							AddEdge(ID(i, j), ID(i + dx[k], j + dy[k]), 1);
 87 					break;
 88 				case 2:
 89 					AddEdge(ID(i, j), T, INF);
 90 					for(int k = 0; k < 4; k++)
 91 						if(i + dx[k] < n && i + dx[k] >= 0
 92 						&& j + dy[k] < m && j + dy[k] >= 0
 93 						&& map[ID(i + dx[k], j + dy[k])] == 0)
 94 							AddEdge(ID(i + dx[k], j + dy[k]), ID(i, j), 1);
 95 					break;
 96 				default:
 97 					for(int k = 0; k < 4; k++)
 98 						if(i + dx[k] < n && i + dx[k] >= 0
 99 						&& j + dy[k] < m && j + dy[k] >= 0
100 						&& map[ID(i + dx[k], j + dy[k])] == 0)
101 							AddEdge(ID(i, j), ID(i + dx[k], j + dy[k]), 1);
102 			}
103 	printf("%d\n", Dinic());
104 
105 	return 0;
106 }//Rhein_E
View Code


转载于:https://www.cnblogs.com/Rhein-E/p/9323589.html

内容概要:本文档详细介绍了一个利用Matlab实现Transformer-Adaboost结合的时间序列预测项目实例。项目涵盖Transformer架构的时间序列特征提取与建模,Adaboost集成方法用于增强预测性能,以及详细的模型设计思路、训练、评估过程和最终的GUI可视化。整个项目强调数据预处理、窗口化操作、模型训练及其优化(包括正则化、早停等手段)、模型融合策略和技术部署,如GPU加速等,并展示了通过多个评估指标衡量预测效果。此外,还提出了未来的改进建议和发展方向,涵盖了多层次集成学习、智能决策支持、自动化超参数调整等多个方面。最后部分阐述了在金融预测、销售数据预测等领域中的广泛应用可能性。 适合人群:具有一定编程经验的研发人员,尤其对时间序列预测感兴趣的研究者和技术从业者。 使用场景及目标:该项目适用于需要进行高质量时间序列预测的企业或机构,比如金融机构、能源供应商和服务商、电子商务公司。目标包括但不限于金融市场的波动性预测、电力负荷预估和库存管理。该系统可以部署到各类平台,如Linux服务器集群或云计算环境,为用户提供实时准确的预测服务,并支持扩展以满足更高频率的数据吞吐量需求。 其他明:此文档不仅包含了丰富的理论分析,还有大量实用的操作指南,从项目构思到具体的代码片段都有详细记录,使用户能够轻松复制并改进这一时间序列预测方案。文中提供的完整代码和详细的注释有助于加速学习进程,并激发更多创新想法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值