USACO Name That Number
题意:一只牛有1-12位数字的铭牌号,每个数字可能代表的字母如下:
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
若以上名字出现在dick.txt文件当中,则输出,若不存在,输出“NONE”。(dick.txt文件中的名字小于5000个, 已按字典排序)
方法:dfs枚举每个可能的名字,用二分在dick.txt文件中查找。
/*
ID: byluolu1
PROG: namenum
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
char s1[10][3] = {'0','0','0','0','0','0','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 s[5000][15];
char t[15], b[15];
int aa, bb;
FILE *ffin = fopen("dict.txt","r");
FILE *fin = fopen("namenum.in","r");
FILE *fout = fopen("namenum.out","w");
void b_search()
{
int l = 0, r = aa - 1;
while(l<=r)
{
int m = (l + r) / 2;
if(strcmp(t, s[m])==0)
{fprintf(fout, "%s\n", s[m]);bb++;return;}
if(strcmp(t, s[m])<0)
r = m - 1;
else if(strcmp(t, s[m])>0)
l = m + 1;
}
}
void dfs(int x, int n)
{
if(x>n)
{
b_search();
return;
}
for(int i=0; i<3; i++)
{
t[x-1] = s1[b[x-1]-'0'][i];
dfs(x+1, n);
}
}
int main()
{
aa = 0, bb = 0;
while(fscanf(ffin, "%s", s[aa++])!=EOF);
fscanf(fin, "%s", b);
int n = strlen(b);
//for(int i=1; i<=n; i++)
t[n]='\0';
dfs(1, n);
if(bb==0)//1、没有符合条件的名字则输出NONE
fprintf(fout, "NONE\n");
return 0;
}
ID: byluolu1
PROG: namenum
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
char s1[10][3] = {'0','0','0','0','0','0','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 s[5000][15];
char t[15], b[15];
int aa, bb;
FILE *ffin = fopen("dict.txt","r");
FILE *fin = fopen("namenum.in","r");
FILE *fout = fopen("namenum.out","w");
void b_search()
{
int l = 0, r = aa - 1;
while(l<=r)
{
int m = (l + r) / 2;
if(strcmp(t, s[m])==0)
{fprintf(fout, "%s\n", s[m]);bb++;return;}
if(strcmp(t, s[m])<0)
r = m - 1;
else if(strcmp(t, s[m])>0)
l = m + 1;
}
}
void dfs(int x, int n)
{
if(x>n)
{
b_search();
return;
}
for(int i=0; i<3; i++)
{
t[x-1] = s1[b[x-1]-'0'][i];
dfs(x+1, n);
}
}
int main()
{
aa = 0, bb = 0;
while(fscanf(ffin, "%s", s[aa++])!=EOF);
fscanf(fin, "%s", b);
int n = strlen(b);
//for(int i=1; i<=n; i++)
t[n]='\0';
dfs(1, n);
if(bb==0)//1、没有符合条件的名字则输出NONE
fprintf(fout, "NONE\n");
return 0;
}
没注意到的地方:
1、“NONE”
2、二分的时候,开始设置继续二分的条件是"l<r",这样漏掉了 “l == r”的情况。
细节才是王道。