1. 程式人生 > 其它 >cf915 C. Permute Digits(搜尋)

cf915 C. Permute Digits(搜尋)

題意:

給定兩個整數 b 和 a ,重排 b ,使得 b 儘量大但是不大於 a。

範圍 1e18,兩數位數不一定相等。保證答案存在。

思路:

開個桶記錄 b[] 中數字出現的次數,cnt[i] 表示當前剩下幾個 i 可以使用。

dfs(int u, bool same) 表示現在要填第 u 位,前面的位是不是完全和 a[] 一樣。每次從9到0找數填,如果 same = true 則還需要求準備填的數不大於 a[u]

#include <bits/stdc++.h>
using namespace std;
int a[21], b[21], ans[21], na, nb;
int cnt[11]; //b[]的桶

bool dfs(int u, bool same)
{
    if(u > nb) return 1;
    if(same)
    {
        for(int i = 9; i >= 0; i--)
            if(cnt[i] && i <= a[u])
            {
                --cnt[i], ans[u] = i;
                if(i == a[u])
                {
                    if(dfs(u+1, 1)) return 1;
                    else ++cnt[i];
                }
                else
                {
                    if(dfs(u+1, 0)) return 1;
                    else ++cnt[i];
                }
            }
        return 0;
    }
    else
    {
        for(int i = 9; i >= 0; i--)
            if(cnt[i])
            {
                --cnt[i], ans[u] = i;
                if(dfs(u+1, 0)) return 1;
                else ++cnt[i];
            }
        return 0;
    }
}
string str;
signed main()
{ //讀進字串再轉成陣列
    cin >> str; nb = str.size();
    for(int i = 0; i < nb; i++) b[i+1] = str[i]-'0', cnt[b[i+1]]++;

    cin >> str; na = str.size();
    for(int i = 0; i < na; i++) a[i+1] = str[i]-'0';

    if(nb < na)
    {
        sort(b + 1, b + 1 + nb, greater<int>());
        for(int i = 1; i <= nb; i++) printf("%d", b[i]);
    }
    else
    {
        if(nb > na) while(nb > na) --cnt[0], --nb; //去掉一些0
        dfs(1, 1);
        for(int i = 1; i <= nb; i++) printf("%d", ans[i]);
    }

    return 0;
}