0
点赞
收藏
分享

微信扫一扫

关于这一周的总结

笑望叔叔 2022-04-13 阅读 57
算法

在这一周里看了一些博客,做了一些题目,但是做的题目有点少,看的都是关于搜索的博客,虽然在搜索方面没什么进展,但是在做题方面有了更多的体会和感悟,尤其是在周六晚上的codeforce上的题目,本来应该做出来的题,硬生生拖到最后还是没做出来,在写代码中出现了慌乱,导致自己都不知道做什么,这是不应该出现的情况。既然出现了这种情况,就应该克服这种情况。另外,看了这么多博客,还是得总结知识,以便以后回看。

以下列举几个典型例题:

1.电路维修(双端队列)

题意:题目是由左上角走到右下角,每个格子都有一个方向不同的对角线,这个题只能沿着对角线走,能改变对角线的方向改变一次操作数加一,求最小的操作数,这是我看到的第一个关于使用双端队列和广度优先搜索一起的。

题解:看的那位大佬的解法,他是用的边权,意思就是如果需要对角线改变方向,那个对角线的边权就为1,如果不需要对角线改变方向,对角线的边权就为0,用双端队列存放数据,边权为1的存放在队尾,而边权为0的存放在队首,那么最终队首元素就是那个操作数最少的元素。

以下是其中的代码:(其中还使用了pair)

#include <iostream>
#include <cstdio>
#include <deque>

using namespace std;
#define long long LL;
const int N = 600;

char str[N][N];
int n, m;
bool vis[N][N];
int dis[N][N];

int main()
{
    int T; 
    cin >> T;
    while (T--)
    {
        cin >> n >> m;
        for (int i = 0; i < n; i++) cin >> str[i];
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= m; j++) vis[i][j] = 0, dis[i][j] = int(2e9);

        if (n + m & 1) { cout << "NO SOLUTION\n"; continue; }

        deque<pair<int, int> > deq;
        deq.push_back({ 0, 0 });
        dis[0][0] = 0;

        while (!deq.empty())
        {
            auto t = deq.front(); deq.pop_front();
            int x = t.first, y = t.second;
            if (vis[x][y]) continue;
            vis[x][y] = 1; // 出队后才是最短距离

            for (int i = x - 1; i <= x; i++)
                for (int j = y - 1; j <= y; j++)
                {
                    int xx = x - 1 + 2 * (i - x + 1), yy = y - 1 + 2 * (j - y + 1);
                    if (i < 0 || i >= n || j < 0 || j >= m || vis[xx][yy]) continue;
                    int& d = dis[xx][yy];

                    if (i - x + 1 + j - y + 1 & 1) {
                        if (str[i][j] == '\\') {
                            d = min(d, dis[x][y] + 1);
                            deq.push_back({ xx, yy });
                        }
                        else {
                            d = min(d, dis[x][y]);
                            deq.push_front({ xx, yy });
                        }
                    }
                    else {
                        if (str[i][j] == '\\') {
                            d = min(d, dis[x][y]);
                            deq.push_front({ xx, yy });
                        }
                        else {
                            d = min(d, dis[x][y] + 1);
                            deq.push_back({ xx, yy });
                        }
                    }
                }
        }
        cout << dis[n][m] << endl;
    }
    system("pause");
    return 0;
}

2.HDU 1429:胜利大逃亡(续)

题意:这个是关于走地图的,有墙有门有钥匙,还有起点和终点,从起点开始走,拿到对应的钥匙,开对应的门,直到走到出口,求最少的操作数是否与过了已经限定好了的时间。

题解:利用三维数组来标记地点,前两维存坐标第三维存钥匙的状态,二进制来存钥匙,用位运算运算来取钥匙和开门,用广搜来做这个题目。

(1<<(m[nex.x][nex.y]-'A'))&nex.key//判断这个门是否能用钥匙开启
tmpkey|=(1<<(m[nex.x][nex.y]-'a'));//遇到钥匙,并存放该钥匙

3.POJ Flip Game

这个是关于位运算的,自己感觉比较典型,顺便写一下。

题意:棋盘中有十六个棋子,除了黑棋就是白棋,如果将一个棋子反转,周围的棋子也应该反转,要求用最少的步数完成对棋子的操作,全部变白或者是全部变黑。

题解:首先,用十六位的二进制来存放棋子,如果棋子为白色,则该位置上数位为1,如果是黑棋,则为0,反转时可以用异或运算来翻转棋子,那么最终状态为十六进制数为0或是65536(二进制:1111111111111111)

以上是对本次学习的总结,主要还是对广搜学的更多一点,对于这次周六的codeforce的做题情况来说非常不满意,主要还是自己学的不是很精,还需要加大做题量和各种知识点的涉及。

举报

相关推荐

一周的总结

又是一周总结

一周学习总结

寒假第一周总结

大一寒假第一周总结

Vue第一周复习总结

第一周学习情况总结

ACM第一周总结(STL)

0 条评论