USACO-Section 1.2 Name That Number[...]

2017-05-29
题目大意:

26个字母对应到数字(除了Q和Z)如下。现输入一个数字N(有112位的
十进制整数,对应于字母组合),且给出一个定义了所有合法字母组合(不超
过5000个)的文件dict.txt,要求按字母递增的顺序输出所有符合给定数字
的合法字母组合。
2: A,B,C     5: J,K,L    8: T,U,V
3: D,E,F     6: M,N,O    9: W,X,Y
4: G,H,I     7: P,R,S

样例输入:

4734

对应于此输入,候选的字母组合为:

GPDG GPDH GPDI GPEG GPEH GPEI GPFG GPFH GPFI GRDG GRDH GRDI
GREG GREH GREI GRFG GRFH GRFI GSDG GSDH GSDI GSEG GSEH GSEI
GSFG GSFH GSFI HPDG HPDH HPDI HPEG HPEH HPEI HPFG HPFH HPFI
HRDG HRDH HRDI HREG HREH HREI HRFG HRFH HRFI HSDG HSDH HSDI
HSEG HSEH HSEI HSFG HSFH HSFI IPDG IPDH IPDI IPEG IPEH IPEI
IPFG IPFH IPFI IRDG IRDH IRDI IREG IREH IREI IRFG IRFH IRFI
ISDG ISDH ISDI ISEG ISEH ISEI ISFG ISFH ISFI

但是根据dict.txt,合法的字母组合只有GREG。所以样例输出为:

GREG

题解:

首先,输入的数字N决定了可能的字母组合有3^N种之多,而合法的字母组合<5000。所以想到先根据字符与数字的对应关系将合法的字母组合集转换成对应的数字集,并将输入的数字先与该数字集进行匹配,若没有匹配则输出”NONE”,程序结束。若有匹配,则记录每次匹配的起点和终点(因为合法的组合集是按递增顺序排列好的,可能会有连续的记录满足条件),而不连续的匹配区间可能有多个,所以要遍历整个合法字母组合集。

思路如上所述-_-||再次吐槽自己的编程水平。。但目前我只想赶快往下刷题,所以个人对此只好先。。。

代码如下(看看就好):

/*
ID: madara01
PROG: namenum
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <string>
#define cin fin
#define cout fout
#define MAX 5001

using namespace std;

int main(int argc, char **argv)
{
    string tname;
    string number;
    string pre_ind[MAX];  //合法名字的数字编号数组
    int i,j,nameNum = 0;
    ofstream fout ("namenum.out");
    ifstream fin ("namenum.in");
    ifstream dic ("dict.txt");
    //泪崩T_T不知道怎么把指针复位到文件开头。。
    //所以,目前只好重新定义一个文件指针-_-||
    ifstream res ("dict.txt");
    for(i = 0; i<MAX; i++)
    {
        if(dic.eof())  break;
        dic >> tname;
        nameNum ++; //合法名字的总数
        for(j = 0; j<tname.length(); j++)
        {  //对应规则
            if('A'<=tname[j] && tname[j]<='C')  pre_ind[i] = pre_ind[i] + "2";
            else if('D'<=tname[j] && tname[j]<='F')  pre_ind[i] = pre_ind[i] + "3";
            else if('G'<=tname[j] && tname[j]<='I')  pre_ind[i] = pre_ind[i] + "4";
            else if('J'<=tname[j] && tname[j]<='L')  pre_ind[i] = pre_ind[i] + "5";
            else if('M'<=tname[j] && tname[j]<='O')  pre_ind[i] = pre_ind[i] + "6";
            else if('P'<=tname[j] && tname[j]<='S' && tname[j]!='Q')  pre_ind[i] = pre_ind[i] + "7";
            else if('T'<=tname[j] && tname[j]<='V')  pre_ind[i] = pre_ind[i] + "8";
            else if('W'<=tname[j] && tname[j]<='Y')  pre_ind[i] = pre_ind[i] + "9";
            else pre_ind[i] = pre_ind[i] + "0";
        }
    }
    nameNum --;
    cin >> number;
    j = 0;
    int temp = 0;
    int ac = 0;  //标识问题是否有解
    while(j < nameNum)  //解区间可能不止一个,所以要循环遍历整个dict
    {
        while(pre_ind[j] != number && j < nameNum)  j++;  //j指向当前第一个符合条件的合法名字
        if(j >= nameNum && ac == 0)  cout << "NONE" << endl;
        else
        {
            ac = 1;
            for(i = j; i < nameNum && pre_ind[i] == number; i++)  ;
            while(temp < j)
            {
                res >> tname;
                temp ++;
            }
            while(temp < i)
            {
                res >> tname;
                cout << tname << endl;
                temp ++;
            }
            j = i;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值