今日训练 三题 搜索

C. King's Path

The black king is standing on a chess field consisting of 109 rows and 109 columns. We will consider the rows of the field numbered with integers from 1 to 109 from top to bottom. The columns are similarly numbered with integers from 1 to 109 from left to right. We will denote a cell of the field that is located in the i-th row and j-th column as (i, j).

You know that some squares of the given chess field are allowed. All allowed cells of the chess field are given as n segments. Each segment is described by three integers ri, ai, bi (ai ≤ bi), denoting that cells in columns from number ai to number bi inclusive in the ri-th row are allowed.

Your task is to find the minimum number of moves the king needs to get from square (x0, y0) to square (x1, y1), provided that he only moves along the allowed cells. In other words, the king can be located only on allowed cells on his way.

Let us remind you that a chess king can move to any of the neighboring cells in one move. Two cells of a chess field are considered neighboring if they share at least one point.

Input

The first line contains four space-separated integers x0, y0, x1, y(1 ≤ x0, y0, x1, y1 ≤ 109), denoting the initial and the final positions of the king.

The second line contains a single integer n (1 ≤ n ≤ 105), denoting the number of segments of allowed cells. Next n lines contain the descriptions of these segments. The i-th line contains three space-separated integers ri, ai, bi (1 ≤ ri, ai, bi ≤ 109, ai ≤ bi), denoting that cells in columns from number ai to number bi inclusive in the ri-th row are allowed. Note that the segments of the allowed cells can intersect and embed arbitrarily.

It is guaranteed that the king's initial and final position are allowed cells. It is guaranteed that the king's initial and the final positions do not coincide. It is guaranteed that the total length of all given segments doesn't exceed 105.

Output

If there is no path between the initial and final position along allowed cells, print -1.

Otherwise print a single integer — the minimum number of moves the king needs to get from the initial position to the final one.

Examples
input
Copy
5 7 6 11
3
5 3 8
6 7 11
5 2 5
output
Copy
4
input
Copy
3 4 3 10
3
3 1 4
4 5 9
3 10 10
output
Copy
6
input
Copy
1 1 2 10
2
1 1 3
2 6 10
output
Copy
-1





这个也是一个bfs,也是一个模板题,但是因为这个图有1e9*1e9所以开数组没法存下
这个就是要处理的重点,我不会。。。然后上网查了,用pair和map
具体看下面的代码


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <iostream>
#include <vector>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e6 + 100;
typedef long long ll;
map<pair<int,int>, int>mp;
queue < pair<int, int>>que;
int sx, sy, gx, gy;
int dx[8] = { 0,0,1,-1,1,1,-1,-1 };
int dy[8] = { 1,-1,0,0,1,-1,-1,1 };

int main()
{
    cin >> sx >> sy >> gx >> gy;
    int n; cin >> n;
    for(int i=0;i<n;i++)
    {
        int r, a, b;
        cin >> r >> a >> b;
        for(int j=a;j<=b;j++)
        {
            mp[make_pair(r, j)] = -1;
        }
    }
    mp[make_pair(sx, sy)] = 0;
    que.push(make_pair(sx, sy));
    while(!que.empty())
    {
        int x = que.front().first;
        int y = que.front().second;
        que.pop();
        if (x == gx && y == gy) break;

        for(int i=0;i<8;i++)
        {
            int tx = x + dx[i];
            int ty = y + dy[i];

            if (tx > 1e9 || ty > 1e9 || tx < 1 || ty < 1) continue;
            if(mp[make_pair(tx,ty)]<0)
            {
                mp[make_pair(tx, ty)] = mp[make_pair(x, y)] + 1;
                que.push(make_pair(tx, ty));
            }
        }
    }
    printf("%d\n", mp[make_pair(gx, gy)]);
    return 0;

}



C. Restore Graph

Valera had an undirected connected graph without self-loops and multiple edges consisting of n vertices. The graph had an interesting property: there were at most k edges adjacent to each of its vertices. For convenience, we will assume that the graph vertices were indexed by integers from 1 to n.

One day Valera counted the shortest distances from one of the graph vertices to all other ones and wrote them out in array d. Thus, element d[i] of the array shows the shortest distance from the vertex Valera chose to vertex number i.

Then something irreparable terrible happened. Valera lost the initial graph. However, he still has the array d. Help him restore the lost graph.

Input

The first line contains two space-separated integers n and k (1 ≤ k < n ≤ 105). Number n shows the number of vertices in the original graph. Number k shows that at most k edges were adjacent to each vertex in the original graph.

The second line contains space-separated integers d[1], d[2], ..., d[n(0 ≤ d[i] < n). Number d[i] shows the shortest distance from the vertex Valera chose to the vertex number i.

Output

If Valera made a mistake in his notes and the required graph doesn't exist, print in the first line number -1. Otherwise, in the first line print integer m (0 ≤ m ≤ 106) — the number of edges in the found graph.

In each of the next m lines print two space-separated integers ai and bi (1 ≤ ai, bi ≤ nai ≠ bi), denoting the edge that connects vertices with numbers ai and bi. The graph shouldn't contain self-loops and multiple edges. If there are multiple possible answers, print any of them.

Examples
input
Copy
3 2
0 1 1
output
Copy
3
1 2
1 3
3 2
input
Copy
4 2
2 0 1 3
output
Copy
3
1 3
1 4
2 3
input
Copy
3 1
0 0 0
output
Copy
-1






这个我觉得是树的问题,可以用dfs写,但是我不太会,所以就没有dfs
然后你观察之后你就会发现,这个d值代表的就是这棵的深度。
所以你就直接建图就好了,
除了第一个根节点只有一个之外,每一个深度的节点数都小于等于上一个深度的节点数,这个就可以判断是不是-1,同时可以求出边的数量,
然后就一层一层的开始建图
我的写法有点小复杂,其实可以更简单




#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <iostream>
#include <vector>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + 100;
typedef long long ll;
struct node
{
    int id, d, num;
    node(int id=0,int d=0):id(id),d(d){}
};
vector<node>vec[maxn];


int main()
{
    int n, k,mx=0;
    cin >> n >> k;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin >> x;
        vec[x].push_back(i);
        mx = max(mx, x);
    }
    if(vec[0].size()!=1)
    {
        printf("-1\n");
        return 0;
    }
    int ans = 0;
    for(int i=1;i<=mx;i++)
    {
        ans += vec[i].size();
        if (i == 1 && vec[i].size() <= vec[i - 1].size() * 1ll * k) continue;
        if(vec[i].size()>vec[i-1].size()*1ll*(k-1))
        {
            printf("-1\n");
            return 0;
        }
    }
    printf("%d\n", ans);
    for(int i=1;i<=mx;i++)
    {
        int num = 0,cnt=0;
        int l = vec[i].size();
        int len = vec[i-1].size();
        while(num<len&&cnt<l)
        {
            int tot = 0;
            while ((tot < k-1||(i==1&&tot<k))&&cnt < l)
            {
                //printf("i=%d num=%d cnt=%d\n", i,num, cnt);
                printf("%d %d\n", vec[i - 1][num].id, vec[i][cnt].id);
                cnt++;
                tot++;
            }
            num++;
            //printf("num=%d cnt=%d\n", num, cnt);
        }
    }
    return 0;
}

B. Phillip and Trains

The mobile application store has a new game called "Subway Roller".

The protagonist of the game Philip is located in one end of the tunnel and wants to get out of the other one. The tunnel is a rectangular field consisting of three rows and n columns. At the beginning of the game the hero is in some cell of the leftmost column. Some number of trains rides towards the hero. Each train consists of two or more neighbouring cells in some row of the field.

All trains are moving from right to left at a speed of two cells per second, and the hero runs from left to right at the speed of one cell per second. For simplicity, the game is implemented so that the hero and the trains move in turns. First, the hero moves one cell to the right, then one square up or down, or stays idle. Then all the trains move twice simultaneously one cell to the left. Thus, in one move, Philip definitely makes a move to the right and can move up or down. If at any point, Philip is in the same cell with a train, he loses. If the train reaches the left column, it continues to move as before, leaving the tunnel.

Your task is to answer the question whether there is a sequence of movements of Philip, such that he would be able to get to the rightmost column.

Input

Each test contains from one to ten sets of the input data. The first line of the test contains a single integer t (1 ≤ t ≤ 10 for pretests and tests or t = 1 for hacks; see the Notes section for details) — the number of sets.

Then follows the description of t sets of the input data.

The first line of the description of each set contains two integers n, k (2 ≤ n ≤ 100, 1 ≤ k ≤ 26) — the number of columns on the field and the number of trains. Each of the following three lines contains the sequence of n character, representing the row of the field where the game is on. Philip's initial position is marked as 's', he is in the leftmost column. Each of the k trains is marked by some sequence of identical uppercase letters of the English alphabet, located in one line. Distinct trains are represented by distinct letters. Character '.' represents an empty cell, that is, the cell that doesn't contain either Philip or the trains.

Output

For each set of the input data print on a single line word YES, if it is possible to win the game and word NO otherwise.

Examples
input
Copy
2
16 4
...AAAAA........
s.BBB......CCCCC
........DDDDD...
16 4
...AAAAA........
s.BBB....CCCCC..
.......DDDDD....
output
Copy
YES
NO
input
Copy
2
10 4
s.ZZ......
.....AAABB
.YYYYYY...
10 4
s.ZZ......
....AAAABB
.YYYYYY...
output
Copy
YES
NO
Note

In the first set of the input of the first sample Philip must first go forward and go down to the third row of the field, then go only forward, then go forward and climb to the second row, go forward again and go up to the first row. After that way no train blocks Philip's path, so he can go straight to the end of the tunnel.

Note that in this problem the challenges are restricted to tests that contain only one testset.

这个题目就是一个bfs的板子,你只要把车向左运动转化成人向右走就好了

还有就是注意人怎么走的,先向右走一格,然后 向上走,向下走,或者不动。

这个你不要以为一直向右走就不要vis标记,如果你没有标记,你会哭的(会爆内存

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <iostream>
#include <vector>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 150;
typedef long long ll;
struct node
{
    int x, y;
    node(int x=0,int y=0):x(x),y(y){}
};
int m, vis[maxn][maxn],sx,sy;
char s[10][maxn];
int dx[3] = { 0,1,-1 };
int dy[3] = { 1,1,1 };

int bfs()
{
    queue<node>que;
    que.push(node(sx, sy));
    vis[sx][sy] = 1;
    while(!que.empty())
    {
        node e = que.front(); que.pop();
        //printf("%d %d\n", e.x + 1, e.y);
        if (s[e.x][e.y+1] != '.') continue;
        for(int i=0;i<3;i++)
        {
            int tx = e.x + dx[i];
            int ty = e.y + dy[i];

            if (vis[tx][ty]) continue;
            if (tx<1 || ty<1 || tx>3) continue;
            if (s[tx][ty] != '.') continue;

            if (ty >= m) return 1;
            if (s[tx][ty + 1] != '.') continue;
            if (ty + 1 >= m) return 1;
            if (s[tx][ty + 2] != '.') continue;
            if (ty + 2 >= m) return 1;

            //printf("tx=%d ty=%d\n", tx, ty);
            vis[e.x][e.y+1] = 1;
            vis[tx][ty] = 1;
            vis[tx][ty + 1] = 1;
            vis[tx][ty + 2] = 1;
            que.push(node(tx, ty + 2));
        }
    }
    return 0;
}


int main()
{
    int t,k;
    cin >> t;
    while(t--)
    {
        cin >> m>>k;
        for(int i=1;i<=3;i++)
        {
            cin >> s[i] + 1;
            for(int j=1;j<=m;j++)
            {
                if (s[i][j] == 's') sx = i, sy = j;
            }
        }
        memset(vis, 0, sizeof(vis));
        int f=bfs();
        if (f) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}



















猜你喜欢

转载自www.cnblogs.com/EchoZQN/p/10691524.html