POJ 1732

题意:每个小写字母对应一个数字,然后给你一串数字和一些单词,找出一些单词对应这些数字,并且使得用的单词数最少。

题解:dp[i]代表覆盖住前i个数字的最小花费,如果s能覆该[i,j]则dp[j]=min(dp[j],dp[i-1]+1),判断能否覆盖方法就多了KMP/HASH/AC自动机都行,map也可以水过。

View Code
 1 #include<cstdio>

 2 #include<cstring>

 3 #include<map>

 4 #include<string>

 5 using namespace std;

 6 const int inf=1000000;

 7 int ma[300],lm[50020];

 8 map<string,int> md;

 9 char word[50020][70];

10 int dp[120],pre[120];

11 int main()

12 {

13     ma['i']=ma['j']='1';

14     ma['a']=ma['b']=ma['c']='2';

15     ma['d']=ma['e']=ma['f']='3';

16     ma['g']=ma['h']='4';

17     ma['k']=ma['l']='5';

18     ma['m']=ma['n']='6';

19     ma['p']=ma['r']=ma['s']='7';

20     ma['t']=ma['u']=ma['v']='8';

21     ma['w']=ma['x']=ma['y']='9';

22     ma['o']=ma['q']=ma['z']='0';

23     char s[120];

24     int n;

25     while(scanf("%s",s+1)!=EOF)

26     {

27         md.clear();

28         scanf("%d",&n);

29         int i,j,k;

30         for(i=1; i<=n; i++)

31         {

32             scanf("%s",word[i]);

33             char tp[70];

34             for(j=0;word[i][j];j++)

35                 tp[j]=ma[word[i][j]];

36             tp[lm[i]=j]='\0';

37             md[tp]=i;

38         }

39         memset(pre,-1,sizeof(pre));

40         for(i=110;i>0;i--)

41             dp[i]=inf;

42         dp[0]=0;

43         for(i=1;s[i]!='\0';i++)

44         {

45             if(dp[i-1]==inf)

46                 continue;

47             if(md.find(s+i)!=md.end())

48                 {

49                     k=md[s+i];

50                     if(dp[i-1+lm[k]]>dp[i-1]+1)

51                     {

52                         dp[i-1+lm[k]]=dp[i-1]+1;

53                         pre[i-1+lm[k]]=k;

54                     }

55                 }

56             for(j=i+1;s[j]!='\0';j++)

57             {

58                 char ch=s[j];

59                 s[j]='\0';

60                 if(md.find(s+i)!=md.end())

61                 {

62                     k=md[s+i];

63                     if(dp[i-1+lm[k]]>dp[i-1]+1)

64                     {

65                         dp[i-1+lm[k]]=dp[i-1]+1;

66                         pre[i-1+lm[k]]=k;

67                     }

68                 }

69                 s[j]=ch;

70             }

71         }

72         if(dp[--i]==inf)

73             printf("No solution.\n");

74         else

75         {

76             int wos[200],top=0;

77             for(; i!=0; i-=lm[pre[i]])

78                 wos[top++]=pre[i];

79             for(int i=top-1; i>0; i--)

80                 printf("%s ",word[wos[i]]);

81             printf("%s\n",word[wos[0]]);

82         }

83     }

84     return 0;

85 }

 

你可能感兴趣的:(poj)