http://acm.hdu.edu.cn/showproblem.php?pid=3460
这题题意我就不想说了,做的真实气死我了。就是把给定数目的单词用他那个“ancient printer”给打印出来,让你把最少按键次数输出来。尼玛,
我最初的想法很简单,就是在ac自动机的基础上去,用深搜来跑。因为要求最少嘛,所以记得当时自己就一直在想怎么能满足最优,先打印存在前后缀长度短的,当时YY了好久,但是总是感觉不行。后来实在没办法才去google的,发现他们的方法特别。。,其实我当时也想到了,但是偏执的想跑一下深搜,结果自己还玩大了。按键次数=单词个数(因为要按print键)+2*总共结点个数(ans)-最长字符串长度(ma)。最长放在最后打印,而且打印完之后可以允许字符依旧存在于打印机之中,不必退格删掉,所以要减去。
代码:
View Code
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> using namespace std; const int maxn=26; struct node { node *next[maxn]; node() { for(int i=0;i<maxn;i++) { if(next[i]==NULL) continue; next[i]=NULL; } } ~node() { for(int i=0;i<maxn;i++) { if(next[i]!=NULL) next[i]=NULL; } } }; inline int max(int a,int b) { return a<b?b:a; } int ma,ans,n; class Trie { public: node *root; Trie() { root=NULL; } void insert(char *s) { if(!root) root=new node(); int len=strlen(s); ma=max(ma,len); node *loca=root; for(int i=0;i<len;i++) { int id=s[i]-'a'; if(loca->next[id]==NULL) { ans++; loca->next[id]=new node(); } loca=loca->next[id]; } } }; int main() { char s[55]; while(~scanf("%d",&n)) { Trie t; ans=ma=0; for(int i=0;i<n;i++) { scanf("%s",s); t.insert(s); } printf("%d\n",n+2*ans-ma); } return 0; }
善待每一天,努力做好自己。
欢迎转载,注明出处。