您的位置:首页 > 其它

CF 593 A 2Char(选择合适的枚举方式)

2016-03-12 17:47 141 查看
题目链接:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  枚举