srm 300 div2 1000(贪心进阶)

来源:互联网 发布:网络嗑瓜子什么意思 编辑:程序博客网 时间:2024/05/17 02:50

题意:
有一个环,上面2n个位置,其中n个互不相同的小写字母。
小写代表车,大写代表车位。
一次操作是指把某辆车直接移动到车位上。
如 BACacb,一个合法的移动顺序是,a, c, b
求出字典序最小的移动顺序,如果无解输出NONE。
思路:
贪心策略:每次取字典序最小的可以移动的车移动, 如果不存在。则无解。
如果最后有解,因为每次取最小,所以自然是最小字典序。
但是,怎么在无解的情况下,其他的取法也不可能有解呢?
假设…c….C….现在最小的可以移动的车是c
如果存在一个合法顺序,把c放到以后来移动。那么c…C之间的一段在c移动之前一定都是空的, 也就意味着c的移动顺序可以被提前。

string notok = "NONE";class CircleOrder{        public:        string firstOrder(string circle)        {        int len = circle.length();        vector<int> used(26), p(26);        fill(used.begin(), used.end(), 1);        rep(i, 0, len-1) if (islower(circle[i])) used[circle[i] - 'a'] = 0;        rep(i, 0, len-1) if (islower(circle[i])) p[circle[i] - 'a'] = i;        string ans = "";        rep(i, 1, len/2) {            int ok = 0, choice;            rep(j, 0, 25) if (used[j] == 0) {                int can = 0;                int pos = p[j];                while ( (islower(circle[pos]) && used[circle[pos] - 'a'] || isupper(circle[pos]) && !used[circle[pos] - 'A'] || circle[pos] - 'a' == j)                    && circle[pos] != j+'a'-('a'-'A')) { pos += 1;if (pos == len) pos = 0;}                if (circle[pos] == j+'a'-('a'-'A')) {ok = 1;choice = j;break;}                pos = p[j];                while ( (islower(circle[pos]) && used[circle[pos] - 'a'] || isupper(circle[pos]) && !used[circle[pos] - 'A'] || circle[pos] - 'a' == j)                    && circle[pos] != j+'a'-('a'-'A')) { pos -= 1;if (pos < 0) pos = len-1;}                if (circle[pos] == j+'a'-('a'-'A')) {ok = 1;choice = j;break;}            }            if (ok) {                ans += choice + 'a';                used[choice] = 1;            }            else                return notok;        }        return ans;        }}
0 0