一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n×nn×n的格点组成,每个格点只有22种状态,.
和#
,前者表示可以通行后者表示不能通行。同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷宫的情况下能不能办到。如果起点或者终点有一个不能通行(为#
),则看成无法办到。
第1行是测试数据的组数kk,后面跟着kk组输入。每组测试数据的第11行是一个正整数n(1≤n≤100)n(1≤n≤100),表示迷宫的规模是n×nn×n的。接下来是一个n×nn×n的矩阵,矩阵中的元素为.
或者#
。再接下来一行是44个整数ha,la,hb,lbha,la,hb,lb,描述A处在第haha行, 第lala列,B处在第hbhb行, 第lblb列。注意到ha,la,hb,lbha,la,hb,lb全部是从00开始计数的。
kk行,每行输出对应一个输入。能办到则输出“YES”,否则输出“NO”。
2
3
.##
..#
#..
0 0 2 2
5
.....
###.#
..#..
###..
...#.
0 0 4 0
【输出样例】
YES
NO
深度搜索,以起点为开始,看它的上下左右四个点是否能通行(没有走过而且路不为‘#’,如果能,就把那个坐标为起点送去下次的深搜,直到找到坐标和目标点一样的点为止,输出yes,或者找完所有能走的路发现到不了就输出no。
#include
using namespace std;
#include
#include
#include
const int N = 110;
int n, a, b, c, d;
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 },st[N][N];
bool flag = false;
void dfs(int x,int y)
{
if (flag)return;
if (x == c && y == d)
{
cout << "YES" << endl;
flag = true;
return;
}
for (int i = 0; i < 4; i++)
{
int xx= x + dx[i], yy = y + dy[i];
if (xx >= 0 && xx < n && yy >= 0 && yy < n && st[xx][yy] == 0 )
{
st[xx][yy] = 1;
dfs(xx, yy);
}
}
}
int main()
{
char s;
int k;
cin >> k;
while (k--)
{
flag = false;
memset(st, 0, sizeof st);
cin >> n;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
cin >> s;
if (s == '#')
{
st[i][j] = 1;
}
}
cin >> a >> b >> c >> d;
if (st[a][b]==1 || st[c][d]==1)
{
cout << "NO" << endl;
continue;
}
dfs(a, b);
if (!flag)
{
cout << "NO" << endl;
}
}
return 0;
}
马在中国象棋以日字形规则移动。
请编写一段程序,给定n×m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
第一行为整数T(T < 10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标n,m,x,y。(0≤x≤n-1,0≤y≤m-1, m < 10, n < 10)。
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0为无法遍历一次。
1
5 4 0 0
【输出样例】
32
深度搜索,这里的方向和之前的上下左右不同了,走日字一共有八种方向,每次判断当前点往八个方向走有没有可以通行的点(没走过的)如果有,就以那个点为起点继续下一次判断,并把那个点的状态更改为已通行,准备两个计数器,一个ans记录走过的点,一个res记录所有的走法,每遍历一个点,ans++,当ans==n*m时,res++。有一点要注意的是,ans初始是1而不是0,因为一开始的起点也算我们遍历过的点,所以起点的状态也要更改为已通行。
#include
using namespace std;
#include
#include
#include
const int N = 15;
int n, m, res = 0;
int d[8][2] = { {1,2},{-1,2},{1,-2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1} }, st[N][N];
void dfs(int x, int y,int ans)
{
if (ans == n * m)
{
res++;
return;
}
for (int i = 0; i < 8; i++)
{
int a = x + d[i][0], b = y + d[i][1];
if (a >= 0 && a < n && b >= 0 && b < m && st[a][b] == 0)
{
st[a][b] = 1;
dfs(a, b, ans + 1);
st[a][b] = 0;
}
}
}
int main()
{
int k,ans;
cin >> k;
while (k--)
{
int x, y;
res = 0;
memset(st, 0, sizeof st);
ans = 1;
cin >> n >> m >> x >> y;
st[x][y] = 1;
dfs(x, y, ans);
cout << res << endl;
}
return 0;
}
问题描述
第四次圣杯战争开始了。 为了收集敌人的情报,言峰绮礼命令他的使魔Assassin将自己的灵体分成n份,分别监视教堂外的长直走道。
Assassin每份灵体的能力不同。 第i份灵体可以监视到的区域是闭区间[ai,bi]。
绮礼想知道,监控范围内的区域的总长度是多少。
比如,第一份灵体的视野是[−1,1],第二份灵体的视野是[0,2],第三份灵体的视野是[3,4]。 那么绮礼能获得的全部视野是[−1,2]∪[3,4],长度为4。
输入格式
第1行有一个整数,表示灵体数量n。 接下来有n行,每行两个整数ai和bi,表示第i个灵体的视野为[ai,bi]。
输出格式
输出一个整数s,表示获得的全部视野的总长度。
样例
plot.in
3
3959 21659
8666 26551
3392 11450
plot.out
23159
解释:[3959,21659]∪[8666,26551]∪[3392,11450]=[3392,26551]
总长度为 26551−3392=23159
数据规模和约定
30% 灵体数量1<=n<=50,每份灵体的视野1<=ai,bi<=210^6
100% 灵体数量1<=n<=10000,每份灵体的视野1<=ai,bi<=210^9
圣杯战争草,话说咒腕的分身有10000个吗。
这题和算法提高 长度统计其实是一样的题(我直接复制之前的答案,改了个数据类型就过了),只不过这题的数太大,要用long long类型。
自定义排序规则,以每个区间的左端点为基准升序排序。然后遍历所有区间,如果当前区间的右端点大于等于下一个区间的左端点,则说明这两个区间可以合并,比如[1,2] 和[2,4]这两个区间就可以合并成[1,4],这样总的覆盖长度就是3,但要注意,合并区间并不是单纯的当前区间的左端点和下一个区间的右端点,这样是错误的,比如[1,4]和[2,3]区间,如果是用当前区间的左端点和下一个区间的右端点合并,那结果就是[1,3],但我们知道这结果是错误的,应该是[1,4],所以合并区间的规则应该是遍历过的区间中最小的数为左端点,最大数为右端点。最后计算差值并累计起来输出即可。
#include
using namespace std;
#include
#include
#include
typedef long long ll;
typedef pairPII;
bool cmp(PII a, PII b)
{
return a.first < b.first;
}
int main()
{
int n;
vectorv;
cin >> n;
for (int i = 0; i < n; i++)
{
ll a, b;
cin >> a >> b;
vectorv1;
v.push_back({ a,b });
}
sort(v.begin(), v.end(), cmp);
ll ans = 0;
ll i = 0, j = 0, star = v[i].first, end = v[i].second;
while (i < n)
{
if (j + 1 < n && end >= v[j + 1].first)
{
end = max(end, v[j + 1].second);
j++;
}
else
{
ans += end - star;
j++;
if (j >= n)break;
star = v[j].first;
end = v[j].second;
i = j;
}
}
cout << ans << endl;
return 0;
}