7/28 每日刷题

hdu 1026 好题 优先队列+递归输出

这个就是基于优先队列的bfs,采用优先队列适用于这种耗时不为1的情况。

至于递归输出,之前也碰到过一次,这种思路真的很巧妙,但让我自己写容易写假,感觉理解的还不是很透彻。

// Problem: Ignatius and the Princess I
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1026
// Memory Limit: 65 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;
int n, m;
struct node
{
    int x, y, t;
    friend bool operator<(node a, node b)
    {
        return a.t > b.t;
    }
};
const int N = 105;
char a[N][N];
int vis[N][N];
int flag[N][N];
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool ok(int x, int y)
{
    if (x < 0 || y < 0 || x >= n || y >= m || a[x][y] == 'X')
        return false;
    return true;
}
int bfs()
{
    int count = 0;
    memset(vis, 0, sizeof(vis));
    memset(flag, 0, sizeof(flag));
    struct node cur, nex;
    cur.x = 0, cur.y = 0;
    vis[cur.x][cur.y] = 1;
    cur.t = 0;
    priority_queue<node> qu;
    qu.push(cur);
    while (!qu.empty())
    {
        cur = qu.top();
        qu.pop();
        // printf("%d %d%d\n", cur.t, cur.x, cur.y);
        if (cur.x == n - 1 && cur.y == m - 1)
        {
            return cur.t;
        }
        for (int i = 0; i < 4; i++)
        {
            nex.x = cur.x + dir[i][0];
            nex.y = cur.y + dir[i][1];

            if (ok(nex.x, nex.y) && !vis[nex.x][nex.y])
            {
                flag[nex.x][nex.y] = i;
                if (a[nex.x][nex.y] <= '9' && a[nex.x][nex.y] >= '1')
                {
                    nex.t = cur.t + a[nex.x][nex.y] - '0' + 1;
                }
                else
                    nex.t = cur.t + 1;
                vis[nex.x][nex.y] = 1;
                qu.push(nex);
            }
        }
    }
    return -1;
}
int cnt;
void show(int x, int y)
{
    if (x == 0 && y == 0)
    {
        return;
    }
    int prex = x - dir[flag[x][y]][0];
    int prey = y - dir[flag[x][y]][1];
    show(prex, prey);
    printf("%ds:(%d,%d)->(%d,%d)\n", cnt++, prex, prey, x, y);
    if (a[x][y] >= '1' && a[x][y] <= '9')
    {
        for (int i = 1; i <= a[x][y] - '0'; i++)
            printf("%ds:FIGHT AT (%d,%d)\n", cnt++, x, y);
    }
}
int main()
{
    while (cin >> n >> m)
    {
        cnt = 1;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                cin >> a[i][j];
            }
        }
        int ans = bfs();
        if (ans == -1)
            puts("God please help our poor hero.");
        else
        {
            printf("It takes %d seconds to reach the target position, let me show you the way.\n", ans);
            show(n - 1, m - 1);
        }
        puts("FINISH");
    }
}

hdu 1026

这题的话就是常规bfs就行,因为每一步耗时都是1s,但是要注意的是剪枝,对于bfs来说最有效的剪枝不就是打标记嘛,目的是不走回头路,但是对于这题来说,有时候可能会出现不得不走回头路的情况,所以只能在炸弹重启装置处打标记。


// Problem: Nightmare
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1072
// Memory Limit: 65 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;
int a[10][10];
int sx, sy;
int fx, fy;
int n, m;
int vis[10][10];
int cnt;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
struct node
{
    int step;
    int x, y, t;
};
bool ok(int x, int y)
{
    if (x < 1 || y < 1 || x > n || y > m || a[x][y] == 0)
        return false;
    return true;
}
void bfs()
{
    memset(vis, 0, sizeof(vis));
    struct node cur, nex;
    cur.step = 0;
    cur.x = sx, cur.y = sy, cur.t = 6;
    vis[cur.x][cur.y] = 1;
    queue<node> qu;
    qu.push(cur);
    while (!qu.empty())
    {
        cur = qu.front();
        qu.pop();
        if (cur.x == fx && cur.y == fy)
        {
            printf("%d\n", cur.step);
            return;
        }
        for (int i = 0; i < 4; i++)
        {
            nex.x = cur.x + dir[i][0];
            nex.y = cur.y + dir[i][1];
            nex.t = cur.t - 1;
            if (ok(nex.x, nex.y) && !vis[nex.x][nex.y] && nex.t > 0)
            {
                if (a[nex.x][nex.y] == 4)
                {
                    nex.t = 6;
                    vis[nex.x][nex.y] = 1;
                }
                nex.step = cur.step + 1;
                qu.push(nex);
            }
        }
    }
    printf("-1\n");
    return;
}
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                cin >> a[i][j];
                if (a[i][j] == 2)
                {
                    sx = i, sy = j;
                }
                if (a[i][j] == 3)
                {
                    fx = i, fy = j;
                }
            }
        }
        bfs();
    }
}

 hdu 1242

这题是优先队列bfs的裸题,没什么说的

// Problem: Rescue
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1242
// Memory Limit: 65 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;
const int N = 205;
char a[N][N];
int vis[N][N];
int n, m;
int sx, sy, fx, fy;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
struct node
{
    int x, y, t;
    friend bool operator<(node a, node b)
    {
        return a.t > b.t;
    }
};
bool ok(int x, int y)
{
    if (x < 1 || x > n || y < 1 || y > m || a[x][y] == '#')
        return false;
    return true;
}
void bfs()
{
    memset(vis, 0, sizeof(vis));
    priority_queue<node> qu;
    struct node cur, nex;
    cur.x = sx, cur.y = sy;
    cur.t = 0;
    vis[cur.x][cur.y] = 1;
    qu.push(cur);
    while (!qu.empty())
    {
        cur = qu.top();
        qu.pop();
        if (cur.x == fx && cur.y == fy)
        {
            printf("%d\n", cur.t);
            return;
        }
        for (int i = 0; i < 4; i++)
        {
            nex.x = cur.x + dir[i][0];
            nex.y = cur.y + dir[i][1];
            if (ok(nex.x, nex.y) && !vis[nex.x][nex.y])
            {
                if (a[nex.x][nex.y] == 'x')
                {
                    nex.t = cur.t + 2;
                }
                else
                    nex.t = cur.t + 1;
                vis[nex.x][nex.y] = 1;
                qu.push(nex);
            }
        }
    }
    puts("Poor ANGEL has to stay in the prison all his life.");
    return;
}
int main()
{
    while (cin >> n >> m)
    {
        memset(a, 0, sizeof(a));
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                cin >> a[i][j];
                if (a[i][j] == 'a')
                {
                    fx = i;
                    fy = j;
                }
                if (a[i][j] == 'r')
                {
                    sx = i;
                    sy = j;
                }
            }
        }
        bfs();
    }
}

其实这些是我很久以前写的题了,当时没写题解

今天我只学了一个离散化,离散化是一种小技巧,对于很大的数据而言,用数组下标可能无法表示,所以采用离散化,把他们的相对关系用下标来表示。

//首先定义一个a 结构体
struct node a {
    int val;
    int order;
};

sort(a+1,a+1+n,cmp)//以val升序排列
b[a[1].order]=1;
for(int i=2,int count=1;i<=n;i++)
{
    if(a[i].val==a[i-1].val)
        b[a[i].order]=count;
    else
        b[a[i].order]=++count;
}

看着蛮抽象,其实弄几个数过一下就理解了,反正就是用较小的count替换了大数val

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值