hdu 4119 Isabella's Message ( 模拟 )

题目:点击打开链接

题意:

给一个n*n的矩阵,n为偶数,矩阵由小写字母和'.'组成,'.'表示空格,再给一个n*n矩阵,由'.'和'*'组成,'*'表示洞,'.'表示障碍。

现在将2张卡片重合,将能看到的字符从上往下从左往右依次取出组成一个新单词。卡片可以顺时针旋转90度,再取出能看到的

单词,一共有4个单词,4个单词再依次组成一个句子,因为卡片是连续转动的,所以4个单词首尾相连,任取一个做句子头,所

以句子一共也是4个。再给m个单词,求出字典序最小的句子并要求句子中每个单词都在给定的m个单词中。

分析:

坐标转换公式

(i,j)——> (j,n-i+1) 坐标变换公式,从1,1开始。

先求出4个字符串,然后改变连接顺序,组成新的4个字符串。然后查找是否全部由单词本中的单词组成。


感想:

弱菜驾驭不了简单的模拟,对于程序的编写能力有待加强。。。

有几个想错的地方:

1、只能将每旋转一个方向得到的一个字符串信息作为一个整体来变换顺序。

      这样就只有四个顺序。

      开始想的是字符单独用队列来调整顺序,这样有些情况跳不出外循环,且将问题复杂化了。

2、关于旋转方向一次得到信息用cmp来按坐标行列大小排序。

      (这个也没想到,还不能应用自如啊= =!)

3、对全局变量,多组测试数据的时候,每次用都要初始化。不然就把他作为局部变量处理,

     每次新的一组测试数据就声明一次。

(。。。。不写了,寝室实在是太吵了,无法思考T_T)


代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

struct node
{
    int x,y;
}t[3000];
char maz[55][55];
char mes[55][55];
string b[5];
string word[110];
vector<int> way[10];
int m,ans,n;

bool cmp(const node &aa,const node &bb)
{
    if(aa.x==bb.x) return aa.y<bb.y;
    return aa.x<bb.x;
}
bool cmp2(vector<int> a,vector<int> b)
{
    for(int i=0;i<a.size();i++)
    {
        if(a[i]<b[i]) return true;
        else if(a[i]>b[i]) return false;
        else a.size()<b.size();
    }
}
int search(int pos,int c)
{
    for(int i=0;i<m;i++)
    {
        int tmp=pos,ok=1;
        for(int j=0;word[i][j];j++)
        {
            if(b[c][tmp++]!=word[i][j])
            {
                ok=0;
                break;
            }
        }
        if(ok&&b[c][tmp]=='.'||b[c][tmp]=='\0')
        {
            way[ans].push_back(i);
            return tmp-1;
        }
    }
    way[ans].clear();
    return -1;
}
int main()
{
    int T,i,j,ca,k;
    scanf("%d",&T);
    for(ca=1;ca<=T;ca++)
    {
        for(i=0;i<5;i++)
            b[i]="";
        string a[5];
        scanf("%d",&n);
        getchar();
        for(i=1;i<=n;i++)
            gets(mes[i]+1);
        for(i=1;i<=n;i++)
            gets(maz[i]+1);
        scanf("%d",&m);
        for(i=0;i<m;i++)
            cin>>word[i];
        sort(word,word+m);

        int rear=0,tmp;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(maz[i][j]=='*')
                {
                    t[rear].x=i;
                    t[rear++].y=j;
                }
            }
        }
        for(i=0;i<4;i++)
        {
            for(j=0;j<rear;j++)
            {
                a[i]+=mes[t[j].x][t[j].y];
                tmp=t[j].x;
                t[j].x=t[j].y;
                t[j].y=n+1-tmp;
            }
            sort(t,t+rear,cmp);     //
        }
        for(i=0;i<4;i++)
        {
            for(k=1,j=i;k<=4;k++,j++)
            {
                j=j%4;
                b[i]+=a[j];
            }
            //cout<<"i="<<i<<' '<<b[i]<<endl;
        }
        ans=0;
        for(i=0;i<4;i++)
        {
            way[ans].clear();
            int j,len=b[i].length();
            for(j=0;j<len;j++)
            {
                if(b[i][j]=='.') continue;
                int tmp=search(j,i);
                if(tmp==-1) break;
                else j=tmp;
            }
            if(j==len) ans++;
        }
        sort(way,way+ans,cmp2);
        if(ans)
        {
            cout<<"Case #"<<ca<<":";
            for(int i=0;i<way[0].size();i++)
            cout<<' '<<word[way[0][i]];
        }
        else
        {
            cout<<"Case #"<<ca<<": FAIL TO DECRYPT";
        }
        cout<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值