CF 593 A 2Char(选择合适的枚举方式)
2016-03-12 17:47
141 查看
题目链接:
CF 593 A 2Char
题意:
给出n个只含小写英文字母的字符串,选择若干字符串,拼成一个最多只含两种字母的最长的字符串,输出最长字符串长度。
分析:
我是选择枚举每个最多只含两种字母字符串,然后遍历其他只含改字符串所拥有字母的字符串,最后在处理下都是单种类字母字符串的拼接,这样写不仅代码冗长,而且也容易出错。
看了别人家的代码,发现可以枚举最终字符串含有的所有可能的字母组合,然后对每种组合遍历所有的字符串,判断每个是不是只含有这种组合。Nice~
CODE:
CF 593 A 2Char
题意:
给出n个只含小写英文字母的字符串,选择若干字符串,拼成一个最多只含两种字母的最长的字符串,输出最长字符串长度。
分析:
我是选择枚举每个最多只含两种字母字符串,然后遍历其他只含改字符串所拥有字母的字符串,最后在处理下都是单种类字母字符串的拼接,这样写不仅代码冗长,而且也容易出错。
看了别人家的代码,发现可以枚举最终字符串含有的所有可能的字母组合,然后对每种组合遍历所有的字符串,判断每个是不是只含有这种组合。Nice~
CODE:
//15MS 0KB #include <cstdio> #include <cstring> #include <cmath> #include <cstring> #include <climits> #include <iostream> #include <algorithm> using namespace std; const int maxn=110; int n,ans; string s[maxn]; int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif while(~scanf("%d",&n)) { for(int i=0;i<n;i++) { cin>>s[i]; } ans=0; for(int i=0;i<26;i++)//枚举26个字母中的每一个字母 { for(int j=i+1;j<26;j++)//符合条件的最优解一定是两种字符(存在不止一种字符时) { int tmp=0; for(int k=0;k<n;k++) { int len=s[k].size(); int flag=1; for(int h=0;h<len;h++) { if(s[k][h]!=i+'a'&&s[k][h]!=j+'a')//字符串包含了不止i,j字符 { flag=0; break; } } if(flag) tmp+=len; } ans=max(ans,tmp); } } printf("%d\n",ans); } return 0; }
//15MS 100KB #include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <climits> using namespace std; const int maxn=1010; int n,cnt,ans; char s[110][maxn]; int vis[30],flag[110],num[110][3],len[110]; int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif while(~scanf("%d",&n)) { memset(flag,0,sizeof(flag)); memset(num,0,sizeof(num)); for(int i=0;i<n;i++) { scanf("%s",s[i]); len[i]=strlen(s[i]); cnt=0; memset(vis,0,sizeof(vis)); for(int j=0;j<len[i];j++) { int t=s[i][j]-'a'+1; if(!vis[t]) { vis[t]=1; cnt++; if(cnt>=3) break; } } if(cnt==3) flag[i]=1;//该字符串含有2个以上种类的字符,废弃 else { if(cnt==2) { num[i][0]=1;//num[i][0]==1表示第i个字符串含有两种字符 int tot=0; for(int j=1;j<30;j++) if(vis[j]) num[i][++tot]=j;//用num[i][1]和num[i][2]分别记录这两个字符 } else//cnt=1;//单一字符合并 { int t; for(int j=1;j<30;j++) if(vis[j]) t=j; for(int j=0;j<i;j++)//查找已有字符是否有同样的单一字符字符串 { if(!flag[j]&&num[j][0]==0&&num[j][1]==t) { len[j]+=len[i];//将已有的同样的单一字符字符串长度增加 flag[i]=1;//现在的字符串废弃 break; } } if(flag[i]!=1)//未成功合并 { num[i][0]=0;//添加新的单一字符串 num[i][1]=t; } } } } int a,b; ans=0; for(int i=0;i<n;i++)//枚举每个字符串 { int tmp=0; if(flag[i]) continue;//字符串已经废弃了 tmp=len[i]; if(num[i][0]==1)//该字符串有两种字符 { a=num[i][1],b=num[i][2]; } else a=num[i][1],b=-1;//只有一种字符 for(int j=0;j<n;j++) { if(i==j||flag[j]) continue; if(b!=-1)//i字符串含有两个字符 { if(num[j][0]==0&&(num[j][1]==a||num[j][1]==b)) tmp+=len[j];//j字符串只含有一个字符 else if(num[j][0]==1)//j字符串含有两个字符 { if(num[j][1]==a&&num[j][2]==b) tmp+=len[j]; if(num[j][1]==b&&num[j][2]==a) tmp+=len[j]; } } else//i字符串只含有一种字符 { if(num[j][0]==0&&num[j][1]==a) tmp+=len[j]; //j字符串必须也只含有一种且字符种类相同 } } ans=max(ans,tmp); } //处理选择两个最长单字符串情况 int max1=0,ind=-1,max2=0; for(int i=0;i<n;i++)//选择最长的单字符串 if(!flag[i]&&num[i][0]==0&&len[i]>max1) { max1=len[i]; ind=i; } for(int i=0;i<n;i++) if(!flag[i]&&num[i][0]==0&&len[i]>max2&&i!=ind) max2=len[i]; //不能用len[i]!=max1来判断重复,因为有可能最长单字符串不止一个 printf("%d\n",max(max1+max2,ans)); } return 0; }
相关文章推荐
- C#编程中枚举类型的使用教程
- 枚举的用法详细总结
- PHP中Enum(枚举)用法实例详解
- c#入门之枚举和结构体使用详解(控制台接收字符串以相反的方向输出)
- 理解C#中的枚举(简明易懂)
- C#枚举中的位运算权限分配浅谈
- C++基础入门教程(四):枚举和指针
- FileShare枚举的使用小结(文件读写锁)
- Java枚举类用法实例
- 枚举窗口句柄后关闭所有窗口示例
- javascript模拟枚举的简单实例
- 深入剖析JavaScript中的枚举功能
- 枚举和宏的区别详细解析
- 深入理解C#中的枚举
- C#实现获取枚举中元素个数的方法
- 结合C++11的新特性来解析C++中的枚举与联合
- java中枚举的详细使用介绍
- java枚举的使用示例
- Java枚举详解及使用实例(涵盖了所有典型用法)
- Java的枚举类型使用方法详解