multiset是多重集,它与set的区别就是,multiset可以有重复元素,set不可以。
在这个题上还了解了如何倒着遍历multiset、set等库函数
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
#define ll long long
#define N 2010
long long int c[5001];
multiset<long long>a01,a10;
bool cmp(long long int a,long long int b)
{
return a>b;
}
//对于这个题,不是简单的先执行1->0中从大到小的改变,再把0->1中按代价从小到大改变,
//并且还要考虑a数组和b数组(字符串)都为1的情况,可能会出现1->0->1的这种情况下,代价最小
int main()
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%lld",&c[i]);
}
string a,b;
cin>>a;
cin>>b;
long long int ss=0;//代表a,b都为1的情况
int s[5001];
int cnt=0;
for(int i=0; i<n; i++)
{
if(a[i]!=b[i])
{
if(a[i]=='1')
{
a10.insert(c[i]);
}
else
{
a01.insert(c[i]);
}
}
else
{
if(a[i]=='1')
{
ss+=c[i];
s[cnt++]=c[i];
}
}
}
long long int minn_sum=ss*(a10.size()+a01.size());//在1->0要执行a10.size()次,0->1要执行a01.size()次
//先把1变成0,并且先把代价大的改变
int i=0;//相当于计数器的作用
for(multiset<long long >::reverse_iterator it=a10.rbegin(); it!=a10.rend(); it++)
{
minn_sum+=(*it)*i;
i++;
}
//再把0变成1,并且先把代价小的改变
i=0;//相当于计数器的作用
for(multiset<long long>::reverse_iterator it=a01.rbegin(); it!=a01.rend(); it++)
{
minn_sum+=(*it)*(i+1);
i++;
}
sort(s,s+cnt,cmp);
for(i=0; i<cnt; i++)
{
long long int sum=0;
a10.insert(s[i]);
a01.insert(s[i]);
ss-=s[i];//s[i]即将被改变,所以从都为1的c[i]总和ss中减掉
sum+=ss*(a10.size()+a01.size());
//下面操作与上面操作亦同,不过是多了1->0->1的过程,都已经加在两个multiset里面了
//先把1变成0,并且先把代价大的改变
int j=0;
for(multiset<long long>::reverse_iterator it=a10.rbegin(); it!=a10.rend(); it++)
{
//cout<<a10[i]<<endl;
sum+=(*it)*j;
j++;
}
//再把0变成1,并且先把代价小的改变
j=0;
for(multiset<long long >::reverse_iterator it=a01.rbegin(); it!=a01.rend(); it++)
{
sum+=(*it)*(j+1);
j++;
}
//cout<<sum<<endl;
minn_sum=min(minn_sum,sum);
}
printf("%lld\n",minn_sum);
return 0;
}