srm 300 div2 1000(贪心进阶)

题意:
有一个环,上面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;
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值