Problem 29 Name That Number

这又是一个简单的全搜索,给出一个数字,每个数字可以对应3个字母,象这样: 2: A,B,C    3: D,E,F    4: G,H,I 等等。。。

再给一个字典,找到这个数字所有的可能性以后再查字典,选出字典里有的词,输出。字典由usaco给出,差不多4千多个词。

最直观的方法就是构建所有的组合,再去查字典。构建的花样不多,查字典的时候小心效率。由于字典是有序的,两分法应该是最好的。

或者反过来,把字典里的词取出来构建数字看符不符合给出的数字。两种方法都可以达到很高的效率。前面一种稍微考点功夫。

我起初用了STL的容器set来放字典,超时~。后来发现字典有序,set毫无意义,换成vector,效率提高10%,依然超时,郁闷~。再换成普通数组,OK,速度翻倍!对比检验网站提供的解法,发现还是比它慢:(貌似string的效果也不理想,还是char*最快。。。

#include <iostream>
#include <fstream>
#include <string>
#include <cmath> // for pow()
using namespace std;

int main(){
 char alphabet[10][3] = {{},{},{'A','B','C'},{'D','E','F'},
    {'G','H','I'},{'J','K','L'},{'M','N','O'},
    {'P','R','S'},{'T','U','V'},{'W','X','Y'}};
 char sn[13]; // 12+1, plus 1 for '/0'
 string name;
 ifstream fin("namenum.in");
 fin.get(sn, 13);
 
 ofstream fout("namenum.out");
 int count = 0;

 ifstream fdict("dict.txt");
 string pname;
 string dict[5000];
 int dp = 0;
 while(getline(fdict, pname)) dict[dp++] = pname;
 
 int i = (int)strlen(sn);
 int* arr = new int[i];
 memset(arr, 0, i * sizeof(int));
 int pos = 0;
 int upper = (int)pow((double)3, i);
 char* tname = new char[13];
 for(int it = 0; it < upper; ++it){
  for(int index = i - 1; index >=0; --index){
   if(arr[index]>2){
    arr[index]=0;
    ++arr[index-1];
   }else break;
  }
  for(int j = 0; j < i; ++j)
   tname[j]=alphabet[sn[j] - 48][arr[j]];
  tname[i]='/0';
  string name(tname);
  while(name > dict[pos]) ++pos;
  if(name == dict[pos]){
   fout<<name<<endl;
   ++count;
  }
  ++arr[i - 1];
 }
 if(count == 0) fout<<"NONE"<<endl;
}

 


Action 2: adding a new user to the library. When the user of the software specifies action 2, your program must add a new user to the library. To add a new user, your program needs to ask the user three things: the role of user (an integer read using readPosInt: the integer 1 represents lender, the integer 2 represents borrower, any other integer must result in an error message "Unknown user role!" being printed and the software going immediately back to the main menu), the name of the user (a string read using readLine), and the initial number of books that the user lends (for a lender) or borrows (for a borrower). You program must then create the correct user, add it to the library, and print an information message. The program then goes back to the menu. For example (where 2, 3, 2, 1, Anna, 5, 2, 2, Bob, and 10 are inputs from the user): Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2 Type the user role (lender:1 borrower:2): 3 Unknown user role! Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2 Type the user role (lender:1 borrower:2): 1 Enter the name of the user: Anna Enter the initial number of borrowed books: 5 Lender "Anna" lending 5 book(s) has been added. Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): 2 Type the user role (lender:1 borrower:2): 2 Enter the name of the user: Bob Enter the initial number of borrowed books: 10 Borrower "Bob" borrowing 10 book(s) has been added. Type an action (total:1 add:2 get:3 more:4 less:5 quit:6): Note that the readPosInt method prevents the initial number of books from being negative, so the constructor for the Borrower class will never throw a NotALenderException when you create a borrower object. Nevertheless the code of the main method of your CLI class must handle this exception by printing the error message "BUG! This must never happen!" and immediately terminating the program using System.exit(1);
05-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值