1. 程式人生 > >【USACO 1.2】 Name That Number 解題報告

【USACO 1.2】 Name That Number 解題報告

\(注意 該篇題解為本人較早時期寫的題解 所以會很傻 直接能用map 以string為下標偏偏要繞彎兒 有時間改一改QAQ\)

[USACO1.2]Name That Number

題目描述

在威斯康辛州牛守志大農場經營者之中,都習慣於請會計部門用連續數字給母牛打上烙印。但是,母牛本身並沒感到這個系統的便利,它們更喜歡用它們喜歡的名字來呼叫它們的同伴,而不是用像這個的語句"C'mon, #4364, get along."。請寫一個程式來幫助可憐的牧牛工將一隻母牛的烙印編號翻譯成一個可能的名字。因為母牛們現在都有手機了,使用標準的按鍵的排布來把將數目翻譯為文字:( 除了 "Q" 和 "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

可接受的名字都被放在這樣一個叫作"dict.txt" 的檔案中,它包含一連串的少於 5,000個(準確地說是4617個)可被接受的牛的名字。 (所有的名字都是大寫的且已按字典序排列) 請讀入母牛的編號並返回那些能從編號翻譯出來並且在字典中的名字。舉例來說,編號 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 碰巧,81箇中只有一個"GREG"是有效的(在字典中)。

寫一個程式來對給出的編號打印出所有的有效名字,如果沒有則輸出NONE。編號可能有12位數字。

輸入輸出格式

輸入格式:

第一行一行包含一個編號(長度可能從1到12)。

接下來4617行,每行一個字串表示可以被接受的名字

輸出格式:

以字典順序輸出一個有效名字的不重複列表,一行一個名字。 如果沒有有效名字,輸出'NONE'。 //註釋:似乎數字只有 \(8^4\) 種排列(1與0不能用)

輸入輸出樣例

輸入樣例#1:

4734
NMSL
GREG
LSDC
....(太多了不寫了)

輸出樣例#1:

GREG

題目 Click Here (洛谷) Click Here (USACO)
這是將名字轉換位數字編碼(神奇的字串雜湊)(注意int存不下,要用long long以上),然後用map儲存用這個數字可得到的名字。
洛谷版程式碼詳見下面QAQ。


dict.txt


這裡是\(USACO\)裡提交通過的程式碼

/*
ID:louhanc1
LANG:C++
TASK:namenum
*/
//USACO要求的格式,不必管它
#include<bits/stdc++.h>
using namespace std;
#define K 103
#define ULL unsigned long long

inline ULL read(){//沒有負數,就把flag去掉了(實際上是懶)
    ULL ans(0); char t(getchar());
    while( !isdigit(t) ) t = getchar();
    while( isdigit(t) ){
        ans = ans * 10 + ( t ^ '0' );
        t = getchar();
    }
    return ans;
}

int key[]={0,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,0,7,7,8,8,8,9,9,9,0};
//key是每個字元轉化成的數字
map<ULL, vector<string> > f;//因為可得到的名字不止一個,所以用vector
ULL N;
string name;
int ans;
vector<string> tmp;//因為map每次訪問f[N]都要一定的時間,所以把結果先存起來

int main(){
    freopen( "dict.txt", "r", stdin );//USACO裡在編譯環境中給了dict.txt 但在洛谷中直接附在便準輸入輸出後面
    while( cin >> name ){
        ULL t(0);
        for ( int i = 0; i < name.size(); ++i )
            t = t * 10 + key[name[i] - 'A' + 1];//轉換成數字
        f[t].push_back(name);//name能由t轉換而來,進f[t]
    }
    freopen( "namenum.in", "r", stdin );
    freopen( "namenum.out", "w", stdout );
    N = read();
    tmp = f[N];
    if ( !tmp.size() ) printf( "NONE\n" );//沒有滿足的名字
    for ( int i = 0; i < tmp.size(); ++i ) cout << tmp[i] << '\n';
    return 0;
}
//finished on 2018/6/3
//at 14:48

\(Luogu\)

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<string>
#include<stack>
#include<iostream>
#include<vector>
#include<cstdlib>
#include<map>
using namespace std;
#define K 103
#define ULL unsigned long long

inline ULL read(){
    ULL ans(0); char t(getchar());
    while( !isdigit(t) ) t = getchar();
    while( isdigit(t) ){
        ans = ans * 10 + ( t ^ '0' );
        t = getchar();
    }
    return ans;
}

int key[]={0,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,0,7,7,8,8,8,9,9,9,0};
map<ULL, vector<string> > f;
ULL N;
string name;
int ans;
//vector<string>::iterator tb, te;
vector<string> tmp;

int main(){
    N = read();
    while( cin >> name ){
        ULL t(0);
        for ( int i = 0; i < name.size(); ++i )
            t = t * 10 + key[name[i] - 'A' + 1];
        f[t].push_back(name);
    }
    if ( !f[N].size() ) printf( "NONE\n" );
    tmp = f[N];
    for ( int i = 0; i < tmp.size(); ++i ) cout << tmp[i] << '\n';
    return 0;
}