URAL1002 PHONE NUMBER
2015-06-08 17:22
260 查看
题意很简单啦,,就像手机键盘,一个数字代表几个字母,问给一串数字,给几个单词,问数字能不能打出下面的几个单词(不用全打),一看就是dp嘛~当然我先用的暴力的做法(懒),明知道有问题就是想测测oj的数据233333(暴力就是直接循环数字串一个字母匹配上了就看剩下的能不能匹配上,能的话这个词就留下,匹配剩下的,有一个数字谁也打不出来就算匹配不上——错误是显而易见的,有的时候后面需要这个词却在前面匹配上了导致后面的匹配不上,,,,,,,)
WA代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char s[50001][51];
int b[50001][51];
char a1[100001];
int a[100001];
char q[50001][51];
void zhuanhuan(int i)
{
int j;
for(j=0;j<strlen(s[i]);j++)
{
if(s[i][j]=='i'||s[i][j]=='j') b[i][j]=1;
if(s[i][j]=='a'||s[i][j]=='b'||s[i][j]=='c') b[i][j]=2;
if(s[i][j]=='d'||s[i][j]=='e'||s[i][j]=='f') b[i][j]=3;
if(s[i][j]=='g'||s[i][j]=='h') b[i][j]=4;
if(s[i][j]=='k'||s[i][j]=='l') b[i][j]=5;
if(s[i][j]=='m'||s[i][j]=='n') b[i][j]=6;
if(s[i][j]=='p'||s[i][j]=='r'||s[i][j]=='s') b[i][j]=7;
if(s[i][j]=='t'||s[i][j]=='u'||s[i][j]=='v') b[i][j]=8;
if(s[i][j]=='w'||s[i][j]=='x'||s[i][j]=='y') b[i][j]=9;
if(s[i][j]=='o'||s[i][j]=='q'||s[i][j]=='z') b[i][j]=0;
}
}
int main()
{
while(scanf("%s",a1)!=EOF)
{
memset(s,0,sizeof(s));
memset(b,0,sizeof(b));
if(a1[0]=='-') break;
int m;
scanf("%d",&m);
int i,j,k;
int t=0;
int glag=0,flag=0;
for(i=0;i<m;i++)
{
scanf("%s",&s[i]);
zhuanhuan(i);
}
int len=strlen(a1);
for(i=0;i<len;i++) a[i]=a1[i]-'0';
for(i=0;i<len;i++)
{
//printf("i = %d\n",i);
for(j=0;j<m;j++)
{
if(a[i]==b[j][0])
{
for(k=1;k<strlen(s[j]);k++)
{
if(b[j][k]!=a[i+k]) break;
//printf("k=%d\n",k);
}
if(k==strlen(s[j]))
{ //printf("*");
flag=1;
strcpy(q[t],s[j]);
t++;
break;
}
}
}
if(flag==1)
{
i=i+k-1;
flag=0;
}
else {glag=1; break;}
}
if(glag==1) printf("No solution.\n");
else
{
for(i=0;i<=t;i++)
{
if(i!=0) printf(" ");
printf("%s",q[i]);
}
printf("\n");
}
}
return 0;
}
(以上完全是占篇幅并没有什么卵用)
这题说实话一开始并没有什么好的DP想法,DP这种东西我觉得不是学了背包什么最长公共字串就能任意写方程了,,,,觉得还是做题的数量还有脑力的问题吧,,,,哎,,还是要加油,,,这题是先看的别人的HINT,然后自己敲的,是这样的:
不想先写代码再解释因为我知道有的人只想看HINT,,,,,,解释一下,,就是如果数字i和数字j之间有单词k,我们就让w[i,j]=1(后面会说到等于单词第K个),这样就有了dp方程//呵呵这里最关键了我看了好多文章都是直接给这个不说为什么,,妈蛋!!我决定不找到为什么就不发这篇。。。
if(w[j][i]!=0)
{
dp[i+j]=min(dp[i],dp[j]+1);
//printf("*\n");
} //比较的是到i之前有几个单词,,,如果之前用的单词就比较少就不用换了。。。。。。重点就是这里!!!要将dp[0]初始化为0,这样如果有一个从0开始的单词,那么dp[0+j]就绝对会是1了,,,然后只有有一个单词可以用首和这个相连(或者与0相连),才会有2或者第一个1,最后如果能到最后一个才是真正的可以完成。。。。问题来了,,如果这个不是dp[j]+1而是直接写成1来标记行不行?自然是可以的!!!只是不是最优的条件(题里说都可以),,所以,,嘿嘿,,路漫漫兮其修远啊,,,,想了好久好久。。。。。。。
然后最后看dp[strlen(a)]是不是inf,,,
还是把AC代码写出来吧,,,如果之前都没懂看看这个吧,,,其实这个已经不太像我的编程习惯了,,,好多都是借鉴来的。。。
#include <iostream
9baa
>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char s[301],word[50001][51],wordlist[27]={0,2,2,2,3,3,3,4,4,1,1,5,5,6,6,0,7,0,7,7,8,8,8,9,9,9,0},k[510],mid[510]; //借鉴大神的设法
int bb=0,g=0,n,f[101],pre[101],ans[1001];
int check(int ii,int jj) //检查能否匹配上,,看过有一个strncmp的,,,但是,,,,不太会= =
{
int j,kk;
if(wordlist[word[jj][0]-'a'+1]==s[ii]-'0')
{
for(j=ii,kk=0;j<ii+strlen(word[jj]);j++,kk++)
if(wordlist[word[jj][kk]-'a'+1]!=s[j]-'0')return 0;
return 1;
}
return 0;
}
void qsort(int l,int r)//一个归并,,,
{
int i,j,kk;
i=l;j=r;
memset(mid,0,sizeof(mid));
strcpy(mid,word[(i+j)/2]);
while(i<=j)
{
while(strcmp(word[i],mid)<0)
i++;
while(strcmp(word[j],mid)>0)
j--;
if(i<=j)
{
if(i==j){i++;j--;continue;}
memset(k,0,sizeof(k));
strcpy(k,word[i]);
for(kk=strlen(word[i])-1;kk!=-1;kk--)
word[i][kk]=0;
strcpy(word[i],word[j]);
for(kk=strlen(word[j])-1;kk!=-1;kk--)
word[j][kk]=0;
strcpy(word[j],k);
i++;j--;
}
}
if(j>l)qsort(l,j);
if(i<r)qsort(i,r);
}
int main()
{
int gg=0;
while(1)
{
bb=0;
memset(word,0,sizeof(word));
memset(s,0,sizeof(s));
memset(ans,0,sizeof(ans));
memset(f,127,sizeof(f)); //127是一个神奇的数字可以去查一查哦~~~
memset(pre,0,sizeof(pre));
scanf("%s",s);
if(s[0]=='-')break; //最开始写-1肯定是没有终止的。。。。。。
scanf("%d",&n);
for(int i=1;i<=n;i++) //输入
scanf("%s",word[i]);
qsort(1,n); //之前一直没用,,这样会提高不少效率吧。。不加肯定也能过的(只是我提交的时候一个速度!!??)也就是说整个归并可以去掉
f[0]=0; //dp
for (int i=0;i<strlen(s);i++)
for (int j=n;j>=1;j--)
if (i+strlen(word[j])<=strlen(s) && f[i]+1<=f[i+strlen(word[j])] && check(i,j)) //中间那里小于也可,,,,如果词word[j]可以放下而且还符合从i到j而且满足动态规划,,
f[i+strlen(word[j])]=f[i]+1,pre[i+strlen(word[j])]=j; //记录每个单词之前的单词是什么!!这步最关键了,,,打印什么的累死了
if(f[strlen(s)]<=10000000) //打印就比较简单了不解释了。。。。
{
int l=0;
for (int u=strlen(s);u!=0;u-=strlen(word[pre[u]]))
ans[++l]=pre[u];
for (int i=l;i;i--)
printf("%s ",word[ans[i]]);
printf("\n");
}
else printf("No solution.\n");
}
return 0;
}
WA代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char s[50001][51];
int b[50001][51];
char a1[100001];
int a[100001];
char q[50001][51];
void zhuanhuan(int i)
{
int j;
for(j=0;j<strlen(s[i]);j++)
{
if(s[i][j]=='i'||s[i][j]=='j') b[i][j]=1;
if(s[i][j]=='a'||s[i][j]=='b'||s[i][j]=='c') b[i][j]=2;
if(s[i][j]=='d'||s[i][j]=='e'||s[i][j]=='f') b[i][j]=3;
if(s[i][j]=='g'||s[i][j]=='h') b[i][j]=4;
if(s[i][j]=='k'||s[i][j]=='l') b[i][j]=5;
if(s[i][j]=='m'||s[i][j]=='n') b[i][j]=6;
if(s[i][j]=='p'||s[i][j]=='r'||s[i][j]=='s') b[i][j]=7;
if(s[i][j]=='t'||s[i][j]=='u'||s[i][j]=='v') b[i][j]=8;
if(s[i][j]=='w'||s[i][j]=='x'||s[i][j]=='y') b[i][j]=9;
if(s[i][j]=='o'||s[i][j]=='q'||s[i][j]=='z') b[i][j]=0;
}
}
int main()
{
while(scanf("%s",a1)!=EOF)
{
memset(s,0,sizeof(s));
memset(b,0,sizeof(b));
if(a1[0]=='-') break;
int m;
scanf("%d",&m);
int i,j,k;
int t=0;
int glag=0,flag=0;
for(i=0;i<m;i++)
{
scanf("%s",&s[i]);
zhuanhuan(i);
}
int len=strlen(a1);
for(i=0;i<len;i++) a[i]=a1[i]-'0';
for(i=0;i<len;i++)
{
//printf("i = %d\n",i);
for(j=0;j<m;j++)
{
if(a[i]==b[j][0])
{
for(k=1;k<strlen(s[j]);k++)
{
if(b[j][k]!=a[i+k]) break;
//printf("k=%d\n",k);
}
if(k==strlen(s[j]))
{ //printf("*");
flag=1;
strcpy(q[t],s[j]);
t++;
break;
}
}
}
if(flag==1)
{
i=i+k-1;
flag=0;
}
else {glag=1; break;}
}
if(glag==1) printf("No solution.\n");
else
{
for(i=0;i<=t;i++)
{
if(i!=0) printf(" ");
printf("%s",q[i]);
}
printf("\n");
}
}
return 0;
}
(以上完全是占篇幅并没有什么卵用)
这题说实话一开始并没有什么好的DP想法,DP这种东西我觉得不是学了背包什么最长公共字串就能任意写方程了,,,,觉得还是做题的数量还有脑力的问题吧,,,,哎,,还是要加油,,,这题是先看的别人的HINT,然后自己敲的,是这样的:
不想先写代码再解释因为我知道有的人只想看HINT,,,,,,解释一下,,就是如果数字i和数字j之间有单词k,我们就让w[i,j]=1(后面会说到等于单词第K个),这样就有了dp方程//呵呵这里最关键了我看了好多文章都是直接给这个不说为什么,,妈蛋!!我决定不找到为什么就不发这篇。。。
if(w[j][i]!=0)
{
dp[i+j]=min(dp[i],dp[j]+1);
//printf("*\n");
} //比较的是到i之前有几个单词,,,如果之前用的单词就比较少就不用换了。。。。。。重点就是这里!!!要将dp[0]初始化为0,这样如果有一个从0开始的单词,那么dp[0+j]就绝对会是1了,,,然后只有有一个单词可以用首和这个相连(或者与0相连),才会有2或者第一个1,最后如果能到最后一个才是真正的可以完成。。。。问题来了,,如果这个不是dp[j]+1而是直接写成1来标记行不行?自然是可以的!!!只是不是最优的条件(题里说都可以),,所以,,嘿嘿,,路漫漫兮其修远啊,,,,想了好久好久。。。。。。。
然后最后看dp[strlen(a)]是不是inf,,,
还是把AC代码写出来吧,,,如果之前都没懂看看这个吧,,,其实这个已经不太像我的编程习惯了,,,好多都是借鉴来的。。。
#include <iostream
9baa
>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char s[301],word[50001][51],wordlist[27]={0,2,2,2,3,3,3,4,4,1,1,5,5,6,6,0,7,0,7,7,8,8,8,9,9,9,0},k[510],mid[510]; //借鉴大神的设法
int bb=0,g=0,n,f[101],pre[101],ans[1001];
int check(int ii,int jj) //检查能否匹配上,,看过有一个strncmp的,,,但是,,,,不太会= =
{
int j,kk;
if(wordlist[word[jj][0]-'a'+1]==s[ii]-'0')
{
for(j=ii,kk=0;j<ii+strlen(word[jj]);j++,kk++)
if(wordlist[word[jj][kk]-'a'+1]!=s[j]-'0')return 0;
return 1;
}
return 0;
}
void qsort(int l,int r)//一个归并,,,
{
int i,j,kk;
i=l;j=r;
memset(mid,0,sizeof(mid));
strcpy(mid,word[(i+j)/2]);
while(i<=j)
{
while(strcmp(word[i],mid)<0)
i++;
while(strcmp(word[j],mid)>0)
j--;
if(i<=j)
{
if(i==j){i++;j--;continue;}
memset(k,0,sizeof(k));
strcpy(k,word[i]);
for(kk=strlen(word[i])-1;kk!=-1;kk--)
word[i][kk]=0;
strcpy(word[i],word[j]);
for(kk=strlen(word[j])-1;kk!=-1;kk--)
word[j][kk]=0;
strcpy(word[j],k);
i++;j--;
}
}
if(j>l)qsort(l,j);
if(i<r)qsort(i,r);
}
int main()
{
int gg=0;
while(1)
{
bb=0;
memset(word,0,sizeof(word));
memset(s,0,sizeof(s));
memset(ans,0,sizeof(ans));
memset(f,127,sizeof(f)); //127是一个神奇的数字可以去查一查哦~~~
memset(pre,0,sizeof(pre));
scanf("%s",s);
if(s[0]=='-')break; //最开始写-1肯定是没有终止的。。。。。。
scanf("%d",&n);
for(int i=1;i<=n;i++) //输入
scanf("%s",word[i]);
qsort(1,n); //之前一直没用,,这样会提高不少效率吧。。不加肯定也能过的(只是我提交的时候一个速度!!??)也就是说整个归并可以去掉
f[0]=0; //dp
for (int i=0;i<strlen(s);i++)
for (int j=n;j>=1;j--)
if (i+strlen(word[j])<=strlen(s) && f[i]+1<=f[i+strlen(word[j])] && check(i,j)) //中间那里小于也可,,,,如果词word[j]可以放下而且还符合从i到j而且满足动态规划,,
f[i+strlen(word[j])]=f[i]+1,pre[i+strlen(word[j])]=j; //记录每个单词之前的单词是什么!!这步最关键了,,,打印什么的累死了
if(f[strlen(s)]<=10000000) //打印就比较简单了不解释了。。。。
{
int l=0;
for (int u=strlen(s);u!=0;u-=strlen(word[pre[u]]))
ans[++l]=pre[u];
for (int i=l;i;i--)
printf("%s ",word[ans[i]]);
printf("\n");
}
else printf("No solution.\n");
}
return 0;
}
相关文章推荐
- Struts2中action接收参数的DomainModel、ModelDriven以及Preparable接口
- POJ1088:滑雪
- 十三周——输入输出流——项目二 用文件保存的学生名单
- 图形处理(六)拖拽式网格融合-Siggraph 2010
- keytool生成证书与Tomcat SSL配置
- POJ1088:滑雪
- [LeetCode] Two Sum
- ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
- LeetCode_24---Swap Nodes in Pairs
- xml
- struts2提交多个对象带图片
- 最大化平均值
- LeetCode83:Remove Duplicates from Sorted List
- IT十年职业发展规划
- 关于Tableview头部添加图片或者其他东西的时候
- Linux-常用命令(2)权限管理命令
- C++——拼接+=
- Timer定时器、TimerTask、Random随机数
- 图形处理(五)基于旋转不变量的网格变形-Siggraph 2007
- C++ 调用webservice 出现 函数返回值为 3 (SOAP_TAG_MISMATCH) 的解决方案