题意
大概是01串接龙,接的时候必须尾首相同。
你可以将其中的串反转,使得最后拼起来但要保证最后没有相同的。
题解
首先可以想到
真正有用的是首尾,单独拿出来可以发现只有四种状态。记录一下即可。
如果00和11都在的话,
连接的就只有00 0110 0110 01 11.这是我一开始想到的。
也就是奇数个。但实际上:00 01 11 11 11 10 01 10 01
这样无论奇数偶数都可以。
我们计算出01和10的个数相加,除以2,会存在有一个会多一个。
对于这种情况我们可以发现,不论是哪种情况多出来的一定是01。
相反以11作开头也是如此。多出来则是10。
分别考虑只有00没有11,只有11没有00.
这里我是没有考虑到的,因为一开始我只想到了00 0110 0110的顺序,所以这样子01一定是多的那个。但是实际上也可以,10 00 0110 0110,也就是10也可以是多的那个。就需要计算两次。
11的情况是类似的。
最后只剩下只有01 10的这个就是计算两次即可。因为两个都可以做多的那个。
因为需要计算多次,写一个函数即可(00和11都在的情况需要特判没有01和10.)
【注意考虑不选会导致重复的,具体做法是开个map判断一下】
#include<bits/stdc++.h>
using namespace std;
string str[200050];
int cnt[4];
vector<int>G[4];
vector<int>T,tmp;
map<string,int>mp;
int ans;
int inv(int id){
if(id==1)return 2;
if(id==2)return 1;
}
void del(int id,int flag){
int num=cnt[1]+cnt[2];
if(flag==1&&num==0)return ;
int ttt;
tmp.clear();
if(abs(cnt[id]-num/2)<ans){
bool ok=true;
ttt=abs(cnt[id]-num/2);
if(cnt[id]>num/2){
if(ttt<=G[id].size()){
for(int i=1;i<=ttt;i++)tmp.push_back(G[id][i-1]);
}
else ok=false;
}
else{
if(ttt<=G[inv(id)].size()){
for(int i=1;i<=ttt;i++)tmp.push_back(G[inv(id)][i-1]);
}
else ok=false;
}
if(ok)ans=ttt,T=tmp;
}
}
int main(){
int Time;cin>>Time;
while(Time--){
int n;cin>>n;
for(int i=0;i<4;i++)G[i].clear();
memset(cnt,0,sizeof(cnt));
mp.clear();
for(int i=1;i<=n;i++){
cin>>str[i];mp[str[i]]=1;
}
for(int i=1;i<=n;i++){
int val=2*(str[i][0]-'0')+str[i][str[i].size()-1]-'0';
cnt[val]++;
reverse(str[i].begin(),str[i].end());
if(!mp[str[i]])G[val].push_back(i);
}
ans=0x3f3f3f3f;T.clear();
if(cnt[0]||cnt[3]){
if(cnt[0]){
if(cnt[3])del(2,1);
else del(2,0),del(1,0);
}
if(cnt[3]){
if(cnt[0])del(1,1);
else del(1,0),del(2,0);
}
}
else{
del(1,0);
del(2,0);
}
if(ans==0x3f3f3f3f){
puts("-1");
continue;
}
cout<<ans<<endl;
for(int i=1;i<=ans;i++)printf("%d ",T[i-1]);puts("");
}
}
来源:CSDN
作者:mxYlulu
链接:https://blog.csdn.net/mxYlulu/article/details/103568806