1:电话号码
源程序名 phone.???(pas, c, cpp) 可执行文件名 phone.exe 输入文件名 phone.in 输出文件名 phone.out |
【问题描述】
电话机上每一个数字下面都写了若干个英文字母。分布如下:
1~abc
2~def
3~ghi
4~jkl
5~mn
6~opq
7~rst
8~uvw
9~xyz
现在给定一个单词表和一串数字密码,请你用单词表中的单词翻译这个密码。
【输入】
第一行为一个正整数N表示单词表中单词的个数(N≤100);
第二行为一个长度不超过100的数字串,表示密码;
接下来的N行,每行一个长度不超过20的单词,表示单词表。
【输出】
仅一行,表示翻译后的原文,如果密码无法翻译,则输出“No Solutions!”,如果密码有多种翻译方式,则输出任意一种即可。
【样例】
phone.in phone.out
8 thi shs b boo k
73373711664
thi
shs
this
is
b
a
boo
k
我考试用的动规,我想复杂度比搜索低得多
然后对拍。。发现有错,结果突然醒悟过来,这个题是有比较程序的。。。我吃多了去写一个对拍。。。
搜索:
#include <cstdio>
#include <string>
#include <cstdlib>
long g[110];
char name[110][30];
char name0[110][30];
char phone[110];
long n;
const long map[] = {1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6,7,7,7,8,8,8,9,9,9};
long getint()
{
long rs=0;char tmp;bool sgn=1;
do tmp = getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){sgn=0;tmp=getchar();}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
void output(long l)
{
if (g[l])
{
printf("%s ",name0[g[l]]+1);
output(l + name[g[l]][0]);
}
}
void dfs(long l)
{
for (long i=1;i<n+1;i++)
{
if (l + name[i][0] > phone[0] + 1)
continue;
bool sgn = true;
for (long j=0;j<name[i][0];j++)
if (name[i][j+1]!=phone[l+j])
{
sgn = false;
break;
}
if (!sgn) continue;
if (l + name[i][0] == phone[0]+1)
{
g[l] = i;
output(1);
exit(0);
}
else
{
g[l] = i;
dfs(l + name[i][0]);
}
}
}
int main()
{
freopen("phone.in","r",stdin);
freopen("std.out","w",stdout);
n = getint();
scanf("%s",phone+1);
while (phone[++phone[0]]){phone[phone[0]]-='0';}
phone[phone[0]--] = -1;
for (long i=1;i<n+1;i++)
{
scanf("%s",name[i]+1);
while(name[i][++name[i][0]])
{
name0[i][name[i][0]] = name[i][name[i][0]];
if (name[i][name[i][0]] > 'Z')
name[i][name[i][0]] = map[name[i][name[i][0]]-'a'];
else
name[i][name[i][0]] = map[name[i][name[i][0]]-'A'];
}
name[i][0] --;
}
dfs(1);
printf("No Solutions!");
return 0;
}
动规:
一开始忘了匹配。。。
while (word[i][++word[i][0]])一开始写成了while (word[i][word[i][0]++]),而且还忘了word[i][0]--。
没有写if (i-word[j][0]<0) continue;造成了死循环。
ouput(l-word[g[l]][0] 写成了 output(l-g[l][0]);
#include <cstdio>
#include <string>
const long map[] = {1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,6,7,7,7,8,8,8,9,9,9};
char phone[110];
char word[110][30];
char word0[110][30];
bool f[110];
long g[110];
long getint()
{
long rs=0;char tmp;bool sgn=1;
do tmp = getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){sgn=0;tmp=getchar();}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
void output(long l)
{
if (l == 0)
{
return;
}
output(l - word[g[l]][0]);
printf("%s ",word0[g[l]]+1);
}
int main()
{
freopen("phone.in","r",stdin);
freopen("phone.out","w",stdout);
long n = getint();
scanf("%s",phone+1);
while (phone[++phone[0]]){phone[phone[0]]-='0';}
phone[0]--;
for (long i=1;i<n+1;i++)
{
scanf("%s",word[i]+1);
while (word[i][++word[i][0]])
{
word0[i][word[i][0]] = word[i][word[i][0]];
if (word[i][word[i][0]]>'Z')
word[i][word[i][0]]=map[word[i][word[i][0]]-'a'];
else
word[i][word[i][0]]=map[word[i][word[i][0]]-'A'];
}
word[i][0] --;
}
f[0] = true;
for (long i=1;i<phone[0]+1;i++)
{
for (long j=1;j<n+1;j++)
{
bool sgn = true;
if (i-word[j][0]<0) continue;
for (long k=0;k<word[j][0];k++)
{
if (word[j][word[j][0]-k] != phone[i-k])
{
sgn = false;
break;
}
}
if (sgn && f[i-word[j][0]])
{
f[i] = true;
g[i] = j;
}
}
}
if (f[phone[0]])
{
output(phone[0]);
}
else
{
printf("No Solutions!");
}
return 0;
}