USACO Section 1.2 Name That Number

题目原文

Name That Number

Among the large Wisconsin cattle ranchers, it is customary to brand cows with serial numbers to please the Accounting Department. The cow hands don't appreciate the advantage of this filing system, though, and wish to call the members of their herd by a pleasing name rather than saying, "C'mon, #4734, get along."

Help the poor cowhands out by writing a program that will translate the brand serial number of a cow into possible names uniquely associated with that serial number. Since the cow hands all have cellular saddle phones these days, use the standard Touch-Tone(R) telephone keypad mapping to get from numbers to letters (except for "Q" and "Z"):

          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

Acceptable names for cattle are provided to you in a file named "dict.txt", which contains a list of fewer than 5,000 acceptable cattle names (all letters capitalized). Take a cow's brand number and report which of all the possible words to which that number maps are in the given dictionary which is supplied as dict.txt in the grading environment (and is sorted into ascending order).

For instance, the brand number 4734 produces all the following names:

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

As it happens, the only one of these 81 names that is in the list of valid names is "GREG".

Write a program that is given the brand number of a cow and prints all the valid names that can be generated from that brand number or ``NONE'' if there are no valid names. Serial numbers can be as many as a dozen digits long.

PROGRAM NAME: namenum

INPUT FORMAT

A single line with a number from 1 through 12 digits in length.

SAMPLE INPUT (file namenum.in)

4734

OUTPUT FORMAT

A list of valid names that can be generated from the input, one per line, in ascending alphabetical order.

SAMPLE OUTPUT (file namenum.out)

GREG

分析

这道题有点类似于手机上的T9键盘,2~9八个按键分别对应三个英文字母,题目要求根据输入的数字(2~9),得到所有可能的英文字母的排列组合,然后再与一个字典文件dict.txt里面的字符对比,如果得到的字符组合出现在字典里,则输出,每一个组合输出一行;
如果按照正常思路,应该根据数字得到所有的组合,再去“查字典”看是否在字典中,然后得到结果;然后,按照输入数字得到所有可能的英文字符组合比较困难,尤其是输入的数字位数比较多的时候,得到所有的可能组合非常耗时。因此可以换一个思路,对字典里的每一个字符串换算得到相应的数字,再与输入的数字对比,如果相同就输出该字符串,否则不输出,因为字典的总数是固定的,所以这个算法的复杂度是固定的,不会随着输入数字的位数增加而增加;

提交代码

/*
ID: 
PROG: namenum
LANG: C++
*/
#include <fstream>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
using namespace std;



int brand(char ch)
{
	if(ch <= 'O')
	{
		return (ch - 'A')/3 +2;
	}
	else if(ch =='P' || ch=='R' || ch == 'S')
	{
		return 7;
	}
	else if(ch =='T' || ch=='U' || ch == 'V')
	{
		return 8;
	}
	else if(ch =='W' || ch=='X' || ch == 'Y')
	{
		return 9;
	}
	else
		return -1;
}


int main()
{
	vector<string> dict;
	string name;
	ifstream fin("dict.txt");
	while(fin >> name)
	{
		dict.push_back(name);
	}
	
	string n;
	ifstream ifile("namenum.in");
	ifile >> n;
	vector<int> num(n.length());
	for (int i=0;i!=n.length();i++)
	{
		num[i] = n[i] - '0';
	}
	ofstream fout("namenum.out");
	bool none = true;
	for (int i=0;i!=dict.size();i++)
	{
		if(dict[i].length() != num.size())
			continue;
		bool issame = true;
		for (int j=0;j!=dict[i].length();j++)
		{	
			issame = issame && (brand(dict[i][j]) == num[j]);
			if(!issame)
				break;
		}
		if(issame)
		{
			fout << dict[i] << endl;
			none = false;
		}
	}
	if (none)
	{
		fout << "NONE" << endl;
	}
	return 0;
}

提交结果

TASK: namenum
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.011 secs, 3496 KB]
   Test 2: TEST OK [0.016 secs, 3496 KB]
   Test 3: TEST OK [0.016 secs, 3496 KB]
   Test 4: TEST OK [0.016 secs, 3496 KB]
   Test 5: TEST OK [0.019 secs, 3496 KB]
   Test 6: TEST OK [0.019 secs, 3496 KB]
   Test 7: TEST OK [0.022 secs, 3496 KB]
   Test 8: TEST OK [0.016 secs, 3496 KB]
   Test 9: TEST OK [0.019 secs, 3496 KB]
   Test 10: TEST OK [0.011 secs, 3496 KB]
   Test 11: TEST OK [0.019 secs, 3496 KB]
   Test 12: TEST OK [0.019 secs, 3496 KB]
   Test 13: TEST OK [0.016 secs, 3496 KB]
   Test 14: TEST OK [0.016 secs, 3496 KB]
   Test 15: TEST OK [0.016 secs, 3496 KB]

All tests OK.

官方参考答案

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char num[12],sol[12];
char dict[5000][13];
int nsolutions = 0;
int nwords;
int maxlen;
FILE *out;

void calc (int charloc, int low, int high) {
    if (charloc == maxlen) {
        sol[charloc] = '\0';
        for (int x = low; x < high; x++) {
            if (strcmp (sol, dict[x]) == 0) {
                fprintf (out, "%s\n", sol);
                nsolutions++;
            }
        }
        return;
   }
   if (charloc > 0) {
        for (int j=low; j <= high; j++){
            if (sol[charloc-1] == dict[j][charloc-1]) {
                low=j;
                while (sol[charloc-1] == dict[j][charloc-1])
                    j++;
                high=j;
                break;
            }
            if (j == high) return;
        }
    }
    if (low > high) return;
    switch(num[charloc]){
      case '2':sol[charloc] = 'A'; calc(charloc+1,low,high);
               sol[charloc] = 'B'; calc(charloc+1,low,high);
               sol[charloc] = 'C'; calc(charloc+1,low,high);
               break; 
      case '3':sol[charloc] = 'D'; calc(charloc+1,low,high);
               sol[charloc] = 'E'; calc(charloc+1,low,high);
               sol[charloc] = 'F'; calc(charloc+1,low,high);
               break; 
      case '4':sol[charloc] = 'G'; calc(charloc+1,low,high);
               sol[charloc] = 'H'; calc(charloc+1,low,high);
               sol[charloc] = 'I'; calc(charloc+1,low,high);
               break; 
      case '5':sol[charloc] = 'J'; calc(charloc+1,low,high);
               sol[charloc] = 'K'; calc(charloc+1,low,high);
               sol[charloc] = 'L'; calc(charloc+1,low,high);
               break; 
      case '6':sol[charloc] = 'M'; calc(charloc+1,low,high);
               sol[charloc] = 'N'; calc(charloc+1,low,high);
               sol[charloc] = 'O'; calc(charloc+1,low,high);
               break; 
      case '7':sol[charloc] = 'P'; calc(charloc+1,low,high);
               sol[charloc] = 'R'; calc(charloc+1,low,high);
               sol[charloc] = 'S'; calc(charloc+1,low,high);
               break; 
      case '8':sol[charloc] = 'T'; calc(charloc+1,low,high);
               sol[charloc] = 'U'; calc(charloc+1,low,high);
               sol[charloc] = 'V'; calc(charloc+1,low,high);
               break; 
      case '9':sol[charloc] = 'W'; calc(charloc+1,low,high);
               sol[charloc] = 'X'; calc(charloc+1,low,high);
               sol[charloc] = 'Y'; calc(charloc+1,low,high);
               break;
   }
}

int main(){
    FILE *in=fopen ("namenum.in", "r");
    FILE *in2=fopen ("dict.txt", "r");
    int j;
    out=fopen ("namenum.out","w");
    for (nwords = 0; fscanf (in2, "%s", &dict[nwords++]) != EOF; )
        ;
    fscanf (in, "%s",&num);
    maxlen = strlen(num);
    calc (0, 0, nwords);
    if (nsolutions == 0) fprintf(out,"NONE\n");
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    FILE *in = fopen ("namenum.in", "r");
    FILE *in2 = fopen ("dict.txt", "r");
    FILE *out = fopen ("namenum.out","w");
    int nsolutions = 0;
    int numlen;
    char word[80], num[80], *p, *q, map[256];
    int i, j;
    map['A'] = map['B'] = map['C'] = '2';
    map['D'] = map['E'] = map['F'] = '3';
    map['G'] = map['H'] = map['I'] = '4';
    map['J'] = map['K'] = map['L'] = '5';
    map['M'] = map['N'] = map['O'] = '6';
    map['P'] = map['R'] = map['S'] = '7';
    map['T'] = map['U'] = map['V'] = '8';
    map['W'] = map['X'] = map['Y'] = '9';
    fscanf (in, "%s",num);
    numlen = strlen(num);
    while (fscanf (in2, "%s", word) != EOF) {
        for (p=word, q=num; *p && *q; p++, q++) {
            if (map[*p] != *q)
                break;
        }
        if (*p == '\0' && *q == '\0') {
            fprintf (out, "%s\n", word);
            nsolutions++;
        }
    }
    if (nsolutions == 0) fprintf(out,"NONE\n");
    return 0;
}

官方给出的方法,第一种即根据输入数字得到所有可能组合再判断,第二种方法则与本文采用的方法类似,这里使用了map这一容器来建立字母与数字的映射,比本文使用函数来实现要更加简便高效。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值