USACO 2007 October Contest, Problem. Obstacle Course SPFA

本文介绍了一种使用SPFA算法解决在一个N*N的方格地图上,从点A到点B最少需要转多少次90度弯的问题。通过定义状态dist[x][y][f]来表示在坐标(x,y)朝向f时的最少转弯次数,利用队列进行层层扩展,最终找到最短路径。

题目

题目描述

Consider an N x N (1 <= N <= 100) square field composed of 1

by 1 tiles. Some of these tiles are impassible by cows and are marked with an 'x' in this 5 by 5 field that is challenging to navigate:

. . B x . 
. x x A . 
. . . x . 
. x . . . 
. . x . . 

Bessie finds herself in one such field at location A and wants to move to location B in order to lick the salt block there. Slow, lumbering creatures like cows do not like to turn and, of course, may only move parallel to the edges of the square field. For a given field, determine the minimum number of ninety degree turns in any path from A to B. The path may begin and end with Bessie facing in any direction. Bessie knows she can get to the salt lick.

N*N(1<=N<=100)方格中,’x’表示不能行走的格子,’.’表示可以行走的格子。卡门很胖,故而不好转弯。现在要从A点走到B点,请问最少要转90度弯几次?

输入输出格式

输入格式:

第一行一个整数N,下面N行,每行N个字符,只出现字符:’.’,’x’,’A’,’B’,表示上面所说的矩阵格子,每个字符后有一个空格。

【数据规模】

2<=N<=100

输出格式:

一个整数:最少转弯次数。如果不能到达,输出-1。

输入输出样例

输入样例#1: 
3
. x A
. . .
B x .
输出样例#1:
2

说明

【注释】

只可以上下左右四个方向行走,并且不能走出这些格子之外。开始和结束时的方向可以任意。

 

分析

对于这道题来说,我们要计算的是最少转弯次数,所以我们就是针对“最少转弯次数”进行SPFA。在这道题的程序当中,用dist[x][y][f]来表示在(x,y)朝向f时的最少转弯次数。分别用0,1,2,3表示从x轴正方向开始逆时针的四个方向(见注释)。SPFA开始时将起点周围的四个点入队,然后进行层层扩展。每次取出队列头部节点,把周围四个符合条件(在界内且没有障碍物)的点入队。若走到新入队的点的朝向与原来不同,那么对应转弯次数加一。

最后提一个我犯的错误(真是愚蠢):判断边界时,由于我习惯从1开始下标,所以0已经是在界外了,那么44行应该是

if (P.x <= 0 || P.x > n || P.y <= 0 || P.y > n)

而不是

if (P.x < 0 || P.x > n || P.y < 0 || P.y > n)

改了这个我还跟同学立flag说还是过不了,结果就过了。(一记清脆的打脸)

程序

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAX = 100 + 1;
 4 const int dx[] = {1,0,-1,0}, dy[] = {0,1,0,-1};
 5 int n;
 6 int dist[MAX][MAX][4];
 7 bool Matrix[MAX][MAX];
 8 struct point
 9 {
10     int x, y;
11 }A,B;
12 struct node
13 {
14     point p;
15     int f;
16 };
17 /*
18  1
19 2 0
20  3
21 */
22 void SPFA()
23 {
24     memset(dist,0x3F,sizeof(dist));
25     queue<node> Q;
26     while (!Q.empty())
27         Q.pop();
28     for (int i = 0; i < 4; i++)
29     {
30         Q.push( (node){ (point){A.x+dx[i], A.y+dy[i]}, i} );
31         dist[A.x+dx[i]][A.y+dy[i]][i] = 0;
32     }
33     while (!Q.empty())
34     {
35         node v = Q.front();
36         Q.pop();
37         for (int i = 0; i < 4; i++)
38         {
39             point P;
40             P.x = v.p.x + dx[i];
41             P.y = v.p.y + dy[i];
42             if (!Matrix[P.x][P.y])
43                 continue;
44             if (P.x <= 0 || P.x > n || P.y <= 0 || P.y > n)
45                 continue;
46             if (i != v.f)
47             {
48                 if (dist[v.p.x][v.p.y][v.f] + 1 < dist[P.x][P.y][i])
49                 {
50                     dist[P.x][P.y][i] = dist[v.p.x][v.p.y][v.f] + 1;
51                     Q.push((node){(point){P.x,P.y},i});
52                 }
53             }
54             else
55             {
56                 if (dist[v.p.x][v.p.y][v.f] < dist[P.x][P.y][i])
57                 {
58                     dist[P.x][P.y][i] = dist[v.p.x][v.p.y][v.f];
59                     Q.push((node){(point){P.x,P.y},i});
60                 }
61             }
62         }    
63     }
64 }
65 int main()
66 {
67     cin >> n;
68     char C;
69     for (int i = 1; i <= n; i++)
70     {
71         for (int j = 1; j <= n; j++)
72         {
73             cin >> C;
74             if (C == '.')
75                 Matrix[i][j] = true;
76             if (C == 'x')
77                 Matrix[i][j] = false;
78             if (C == 'A')
79             {
80                 Matrix[i][j] = true;
81                 A.x = i;
82                 A.y = j;
83             }
84             if (C == 'B')
85             {
86                 Matrix[i][j] = true;
87                 B.x = i;
88                 B.y = j;
89             }
90         }
91     }
92     SPFA();
93     if (min(min(min(dist[B.x][B.y][0],dist[B.x][B.y][1]),dist[B.x][B.y][2]),dist[B.x][B.y][3]) == 0x3F3F3F3F)
94         cout << -1 << endl;
95     else
96         cout << min(min(min(dist[B.x][B.y][0],dist[B.x][B.y][1]),dist[B.x][B.y][2]),dist[B.x][B.y][3]) << endl;
97     return 0;
98 }

 

 

 

转载于:https://www.cnblogs.com/OIerPrime/p/8387512.html

内容概要:本文研究了一种基于改进ICEEMDAN的火电-蓄电池-飞轮混合储能联合调频协同控制策略,旨在提升电力系统频率调节的快速响应能力与运行稳定性。通过引入改进的自适应噪声完备集合经验模态分解(ICEEMDAN)方法,对电网频率偏差信号进行多时间尺度分解,精确分离高频与低频动态分量,并据此实现功率的差异化分配:高频成分由响应迅速的飞轮储能承担,低频成分由能量密度高的蓄电池处理,同时结合火电机组的基础调频能力,构建火电-混合储能多源协同控制架构。该策略充分发挥各类储能技术的优势,有效缓解单一储能系统的压力,延长设备寿命,并提升系统整体调频性能。文中提供了完整的Matlab仿真代码实现,验证了该方法在抑制频率波动、优化储能出力、提高系统可靠性和经济性方面的显著效果。; 适合人群:具备电力系统分析、自动控制理论及新能源技术等相关专业知识背景,熟悉Matlab/Simulink仿真平台,从事电力系统调频控制、混合储能系统优化、多时间尺度能量管理等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入研究混合储能系统在电网一次调频与二次调频中的功率分配机制与协调控制逻辑;②掌握ICEEMDAN信号分解技术在能源系统动态特征提取与多尺度控制中的应用方法;③实现火电机组与多类型储能协同参与调频的仿真建模、算法开发与性能对比分析;④为综合能源系统、微电网及新型电力系统的多源多时间尺度协调控制提供理论依据与技术参考。; 阅读建议:建议结合提供的Matlab代码逐模块分析算法实现流程,重点理解信号分解、模态分量判别、功率分配规则及控制器设计等关键环节,可通过调整系统参数、模拟不同扰动工况进行仿真测试,进一步开展灵敏度分析与策略优化,以深化对协同控制机理的认识并拓展其实际应用价值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值