• [第三场T2]Pohlepko


    题目描述

    Greedy得到了一块棋盘作为生日礼物。棋盘有N行M列,每个格子中都有一个小写英文字母。在他的生日聚会上,每个人都很无聊,所以他们决定用棋盘玩一个简单的游戏。 首先在左上角标有坐标(1,1)的格子放置一个棋子。在每一个回合中,我们必须将芯片向右或向下移动一格,前提是没有移出棋盘。游戏结束时,将棋子移动到标有坐标(N,M)的格子即棋盘的右下角。在游戏中,我们依次记下移动棋子时经过的格子里的字母,从而构造一个单词。游戏的目标是找到能构造出的字典序最小的单词。 那些成功地构造了字典序最小单词的玩家会得到一袋糖果作为奖励。Greedy愿意付出任何代价来赢得糖果,所以他要求你写一个程序,可以找到能构造出的字典序最小的单词。

    输入

    第一行输入包含整数N和M(1≤N,M≤2000)。表示场地的行数和列数。 接下来N行每行包含一个字符串,每个字符串由M个小写英文字母组成。表示棋盘。

    输出

    输出一个字符串。表示能构造出的字典序最小的单词。
    样例输入

    4 5
    ponoc
    ohoho
    hlepo
    mirko


    样例输出

    pohlepko

    对于50%的数据,每个格子下方和右方的格子中的字母是不同的。

    解题思路

    很明显,一半的点可以直接做,因为它下方和右方的字母不同,我们直接往字典序小的那一个字母遍历即可,当时便是这样暴力,然后相等就一起dfs

    如果有相同的,我们就必须要都两个点都要进行遍历,直到其中一个字符串小于另一个字符串,我们就停止另一个字符串的遍历。

    于是我们用flag打上标记,用一些神奇的操作可以完成这个遍历。

    但好像可以用BFS来判断一下,因为层层扩散的缘故,我们可以只要当前层最优的那一些解(相同的)继续往下搜,其余的不要了。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int n,m,cnt;
    char ans[20005],c[2005][2005];
    bool flag [2005][2005];
    int main(){
    	//freopen("pohlepko.in","r",stdin);
    	//freopen("pohlepko.out","w",stdout);
    	scanf ("%d%d",&n,&m);
    	for (int i = 1;i <= n;i ++){
    		scanf ("
    ");
    		for (int j = 1;j <= m;j ++){
    			scanf ("%c",&c[i][j]);
    		}
    	}
    	ans[++ cnt] = c[1][1];
    	flag[1][1] = 1;
    	for (int i = 2;i < n + m;i ++){//枚举走的步数,最多为n - 1步
    		char p = 'z' + 1;
    		for (int j = 1;j <= min(n,i - 1);j ++){//枚举行数,然后步数减行数得到了列数
    			if (i - j <= m && flag[j][i - j]){//当前点已经遍历
    				flag[j + 1][i - j] = flag[j][i - j + 1] = 1;//先打上标记,等下再处理
    				if (c[j + 1][i - j] >= 'a' && c[j + 1][i - j] <= 'z')//边界情况
    					p = min(p,c[j + 1][i - j]);//向下走
    				if (c[j][i - j + 1] >= 'a' && c[j][i - j + 1] <= 'z')
    					p = min(p,c[j][i - j + 1]);//向右走
    			}
    		}
    		ans [++ cnt] = p;//储存最小的那一个
    		for (int j = 1;j <= min(n,i);j++){
    			if (i - j + 1 <= m && flag[j][i - j + 1] && c[j][i - j + 1] != p)//这里删除标记,如果下,右相等,则暂时不会去标,等之后再形成新的字符串再次去标,+1则是因为已经走了这一步。
    				flag[j][i - j + 1] = 0; 
    		}
    	}
    	for (int i = 1;i <= cnt; i ++)
    		printf("%c",ans[i]);
    }
  • 相关阅读:
    RQNOJ 342 最不听话的机器人:网格dp
    RQNOJ 329 刘翔!加油!:01背包
    RQNOJ 57 找啊找啊找GF:01背包
    RQNOJ 202 奥运火炬登珠峰:01背包
    RQNOJ 201 奥运大包围:LIS + 拼链成环
    2017SN多校D1T2 note:dp
    2017SN多校D1T1 loveletter:模拟
    HDU 2157 How many ways??:矩阵快速幂【i到j共经过k个节点的方法数】
    poj 3764 The xor-longest Path
    bzoj 1192 鬼谷子的钱袋
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566674.html
Copyright © 2020-2023  润新知