原题链接:http://codeforces.com/contest/1102/problem/D
题目大意:给出一个只含0,1,2的字符串序列,长度为N,要求通过最少的变换次数(0变为1或2;1变为2或0;2变为0或1)使串中0,1,2出现次数相等,并且字典序最小。
思路:暴力解决,强行通过个数大小关系进行修改,思维图如下:
代码:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int n;
char str[300100];///输入字符串
priority_queue <int,vector<int>,less<int> >a,b,c;///大到小队列(不会双向所以只能这样了)
int main()
{
cin>>n;///总数
int m = n/3;///平均数
int aa, bb, cc;///012数量
aa = bb = cc = 0;
for(int i = 0; i < n; i++)///输入&&记录
{
cin>>str[i];
if(str[i] == '0')
{
a.push(i);
aa++;
}
if(str[i] == '1')
{
b.push(i);
bb++;
}
if(str[i] == '2')
{
c.push(i);
cc++;
}
}
if(aa==bb&&bb==cc)///特殊情况
{
cout<<str<<endl;
return 0;
}
///具体过程
if(aa>m)
{
if(bb>m)
{
for(int i=0;i<aa-m;i++)
{
int t = a.top();
a.pop();
str[t]='2';
}
for(int i=0;i<bb-m;i++)
{
int t = b.top();
b.pop();
str[t]='2';
}
}else{
if(cc>m)
{
for(int i=0;i<aa-m;i++)
{
int t = a.top();
a.pop();
str[t]='1';
}
for(int i=0;i<m;i++)c.pop();
for(int i=n/3;i<cc;i++)
{
int t = c.top();
c.pop();
str[t]='1';
}
}else{
for(int i=cc;i<m;i++)
{
int t = a.top();
a.pop();
str[t]='2';
}
for(int i=bb;i<m;i++)
{
int t = a.top();
a.pop();
str[t]='1';
}
}
}
}
else{
if(bb>m)
{
if(cc>m)
{
for(int i=0;i<m;i++)b.pop();
for(int i=m;i<bb;i++)
{
int t = b.top();
b.pop();
str[t]='0';
}
for(int i=0;i<m;i++)c.pop();
for(int i=m;i<cc;i++)
{
int t = c.top();
c.pop();
str[t]='0';
}
}else{
for(int i=cc;i<m;i++)
{
int t = b.top();
b.pop();
str[t]='2';
bb--;
}
for(int i=0;i<m;i++)b.pop();
for(int i=m;i<bb;i++)
{
int t = b.top();
b.pop();
str[t]='0';
}
}
}else{
for(int i=0;i<m;i++)c.pop();
for(int i=bb;i<m;i++)
{
int t=c.top();
c.pop();
str[t]='1';
cc--;
}
for(int i=m;i<cc;i++)
{
int t=c.top();
c.pop();
str[t]='0';
}
}
}
cout<<str<<endl;
return 0;
}