noip模拟赛第一题单词(7月26日)

来源:互联网 发布:计算机数据单位 编辑:程序博客网 时间:2024/05/18 01:01

【问题描述】

有一个有字母表,一共有NM列,你从左上角开始出发,目的地是右下角。每次你只能往右或往下走一步。将你经过的格子里面的字母按照访问顺序组成一个单词。求你能得到的字典序最小的单词是什么?

【输入】

第一行包含NM,(1<=N,M<=2000

接下来N行,每行包含M个小写字母。

【输出】

输出最小字典序的单词。

40%的数据,每个格子的右、下的字母不同。

【输入输出样例1

 

word.in

word.out

4 5

ponoc

ohoho

hlepo

mirko

pohlepko

 

 

 

【输入输出样例2】

word.in

word.out

4 5

bbbbb

bbbbb

bbabb

bbbbb

bbbbabbb

 

 

【输入输出样例3】

word.in

word.out

2 5

qwert

yuiop

qweiop


题解:

这道题的话,开始被以前做过的一道类似的题给洗脑了,几乎一样,只是矩阵不是字符,求的是路径上的经过点的和的最小值,想都没怎么想就写了这个思路,心想最小字典序和这个不是一样的吗,然后开心的得了20分滚粗。。。

所以以后要一定要注意:对于最小字典序来说,大小关系是按照从前往后来,只要前面的小胜过另一个后面所有的都小

正解的做法不常规,但也并不难想到,从(1,1)开始,只要该点下面和右边的字符不同,就直接可以选择小的那个了,这个策略也和最小字典序有关,如果相同,则将这两个节点都拓展到下一层,如此循环,直到有节点不同为止,取较小的那个节点,因为内存限制是64M,所以为了防止爆内存,用两个队列实现,一个队列负责处理拓展出的节点,一个队列负责去重以及取出最小的字符。个人觉得这个代码不好解释,本人已经尽力了,但要是直接看代码的话,应该是比较好理解的,因为本人就是这么理解过来的。

code:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<deque>const int MAXN=2005;using namespace std;struct node{    int x,y;char c;    node(){}    node(char s,int a,int b){        c=s; x=a; y=b;    }};queue<node> Q1;deque<node> Q2;char s[MAXN][MAXN];bool vis[MAXN][MAXN];int n,m;inline void Read(int &Ret){    char ch;bool flag=0;    for(;ch=getchar(),ch<'0'||ch>'9';)if(ch=='-')flag=1;    for(Ret=ch-'0';ch=getchar(),'0'<=ch&&ch<='9';Ret=Ret*10+ch-'0');    flag&&(Ret=-Ret);}void Push(node x){    while(!Q2.empty()&&Q2.back().c>x.c) Q2.pop_back();    if(Q2.empty()||Q2.back().c==x.c) Q2.push_back(x);}int main(){    Read(n); Read(m);    for(int i=1;i<=n;i++)        scanf("%s",s[i]+1);    putchar(s[1][1]);    if(n==1&&m==1) return 0;    Q1.push(node(s[1][1],1,1));    while(true)    {        while(!Q1.empty())        {            int i=Q1.front().x,j=Q1.front().y; Q1.pop();            if(i<n) Push(node(s[i+1][j],i+1,j));            if(j<m) Push(node(s[i][j+1],i,j+1));        }        putchar(Q2.front().c);        while(!Q2.empty())        {            int i=Q2.front().x,j=Q2.front().y;            if(i==n&&j==m) return 0;            if(!vis[i][j])                vis[i][j]=1,Q1.push(Q2.front());            Q2.pop_front();        }    }}


阅读全文
0 0
原创粉丝点击