Gym 102501 F Icebergs —— 贪心

This way

题意:

有s种动物,T种交换可能,就是说两个动物如果相邻并且他们有交换可能,你就可以交换这两种动物,最后是N只动物,让你在不违反交换可能的前提下使得他们最终排列的字典序最小。

题解:

这道题不错啊,我没有想对,也没时间敲了。
对于没有交换可能的两只动物来说,它们的先后顺序一定不会变。那么Q[i]队列就表示第i种动物有多少中断,也就是有多少不可交换的位置。那么我们枚举答案的位置,那么ans优先队列表示在这个位置的所有交换可能中,字典序最小的数是什么。之后枚举ans.top离开了以后,后面有哪些数可以交换到下一个位置了,No数组就表示每种数可以到第几个了。

#include<bits/stdc++.h>
using namespace std;
string s[205];
unordered_map<string,int>Id;
int a[100005];
int mp[205][205],No[205],pos[205];
queue<int>Q[205];
priority_queue<int,vector<int>, greater<int> >ans;
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    int S,L,N;
    cin>>S>>L>>N;
    for(int i=1;i<=S;i++)
        cin>>s[i];
    sort(s+1,s+1+S);
    int cnt=0;
    for(int i=1;i<=S;i++)
        Id[s[i]]=++cnt;
    string s1,s2;
    for(int i=1;i<=L;i++){
        cin>>s1>>s2;
        int v1=Id[s1],v2=Id[s2];
        mp[v1][v2]=mp[v2][v1]=1;
    }
    for(int i=1;i<=S;i++)
        mp[i][i]=0;
    for(int i=1;i<=N;i++)
        cin>>s1,a[i]=Id[s1];
    for(int i=1;i<=S;i++){
        int num=0;
        for(int j=1;j<=N;j++){
            if(a[j]==i)
                Q[a[j]].push(num);
            if(mp[a[j]][i]==0)
                num++;
        }
    }
    for(int i=1;i<=N;i++){
        for(int j=1;j<=S;j++){
            while(!Q[j].empty()&&No[j]>=Q[j].front()){
                ans.push(j);
                Q[j].pop();
            }
        }
        cout<<s[ans.top()]<<" ";
        for(int j=1;j<=S;j++)
            if(mp[ans.top()][j]==0)
                No[j]++;
        ans.pop();
    }
    cout<<endl;
    return 0;
}

发布了554 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/104600384