S 老师的签到 dp bfs

dp:

#include<bits/stdc++.h>
#define int long long

using namespace std;
const int N=1e3+50;
int n,m;
char s[N][N];
string f[N];//当前行第j列的值
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        for (int j = 1; j <= m; j++) {
            cin >> s[i][j];//1~n和1~m存储
        }
    }
    f[1]=s[1][1];//第一行第一列
    for(int i=2;i<=m;i++)//更新第一行2~m列的值
        f[i]=f[i-1]+s[1][i];
    for(int i=2;i<=n;i++)//从第二行开始
    {
        f[1]+=s[i][1];//第一列其实和第一行一样,每次直接加就行了(第i行,第1列)
        for(int j=2;j<=m;j++)//第i行,第j列
        {
            f[j]=min(f[j-1],f[j])+s[i][j];
        }
    }
    cout<<f[m];//输出第m列的值(当前已经是第n行了)
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
    int T=1;
//	cin>>T;
    while(T--)
    {
        solve();
    }
    return 0;
}

bfs:

#include <bits/stdc++.h>
using namespace std;
const int N = (1 << 10) + 21;
char g[N][N];//存储输入的字符
int vis[N][N];//标记每个位置是否被访问过。
char ans[N * 2];//用于存储生成的新字符串。
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i = 1; i <= n ;++i)
        cin>>(g[i] + 1);
    int c = 0;
    vector<pair<int,int>> q[2];
    int w = 0;//用于记录新字符串的长度。
    ans[w] = g[1][1];
    vis[1][1] = 1;//表示该位置已被访问过。

    /*
     * 使用两个队列
     * 来存储当前层和下一层的信息。
     */
    q[c].push_back({1, 1});

    //遍历n+m-2次,每次更新当前层和下一层的信息。
    /*
     * 首先清空下一层的队列q[c]
     * 然后遍历当前层的队列q[c^1]
     * 找到当前层中最小的字符mi。
     */

    /*
     * 假设我们有一个n行m列的二维数组g
     * 我们需要从左上角(1,1)出发
     * 每次只能向右或向下移动,最终到达右下角(n,m)
     * 根据这个规则,我们可以得出总共需要移动的次数为n+m-2次。
     */

    for(int i = 1; i <= n + m - 2; ++i) {

        /*
         * c是一个整数,用于在两个队列q[0]和q[1]之间切换
         * 初始时,c被赋值为0。每次循环开始时,c都会与1进行异或操作
         * 这会导致c的值在0和1之间交替变化。
         * 具体来说,异或操作的效果如下:
         * 当c为0时,c ^= 1会使c变为1。
         * 当c为1时,c ^= 1会使c变回0。
         * 因此,c ^= 1的作用是在每次循环中
         * 将c的值翻转,从而实现在两个队列之间交替添加元素的目的
         * 需要交替处理当前层和下一层的节点。
         */
        c ^= 1; q[c].clear();
        // 此时q[c]相当去下一个层信息,
        // 而q[c ^ 1]相等于当前层信息
        char mi = 'z';
        // 从当前层得到最小的字符
        for(auto &t: q[c ^ 1]) {
            int x = t.first, y = t.second;
            if(x < n) mi = min(mi, g[x + 1][y]);
            if(y < m) mi = min(mi, g[x][y + 1]);
        }
        // 记录贡献
        //将mi添加到新字符串ans中,并更新长度w。
        ans[++w] = mi;

        // 根据当前层信息,处理出下一层的信息
        for(auto &t: q[c ^ 1]) {
            int x = t.first, y = t.second;
            if(x < n && g[x + 1][y] == mi && !vis[x + 1][y]) {
                vis[x + 1][y] = 1;
                q[c].push_back({x + 1, y});
            }
            if(y < m && g[x][y + 1] == mi && !vis[x][y + 1]) {
                vis[x][y + 1] = 1;
                q[c].push_back({x, y + 1});
            }
        }
    }
    cout<<ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值