动态规划0pts玄关求调
查看原帖
动态规划0pts玄关求调
992367
liserver楼主2024/10/27 15:17
#include <bits/stdc++.h>

const int MAXN = 1e5 + 5;
const int INF = INT_MAX;

// 打表天下第一
const int table[] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
// 所有可能的数字
const int possible_number[] = {0, 1, 2, 4, 7, 8};
// 不含前导零
const int begin_number[] = {6, 1, 2, 4, 7, 8};
// 根据木棍数量 最小数字
const int minest_number[] = {INF, INF, 1, 7, 4, 2, 0, 8};
// 列表长度
const int len_lists = sizeof(possible_number) / sizeof(int);
// minest_number 长度
const int mnumber_size = sizeof(minest_number) / sizeof(int);

// 按照字符串意义拼接两个数字
// e.g: linK(2, 8) = 28
int link(int a, int b)
{
    if (b == 0)
    {
        return a * 10;
    }

    int result = a;

    result *= (int)std::pow(10, (int)std::log10(b) + 1);
    result += b;

    return result;
}

// 状态转移方程(i是possible_number中的数字)
// dp[n] = min{dp[n], link(i, dp[n - table[i]])}
int dp[MAXN] = {0};
int zero[MAXN] = {0};

int main()
{
    int T;
    std::cin >> T;

    for (int i = 0; i < mnumber_size; i ++)
    {
        dp[i] = minest_number[i];
    }

    while (T --)
    {
        int n;
        std::cin >> n;

        if (n == 6)
        {
            std::cout << 0 << "\n";
            
            continue;
        }

        if (n <= 7)
        {
            std::cout << ((minest_number[n] == INF) ? (-1) : (minest_number[n])) << "\n";

            continue;
        }

        // 更新状态
        for (int i = mnumber_size; i < n; i ++)
        {
            dp[i] = INF;
            zero[i] = 0;

            for (int j = 0; j < len_lists; j ++)
            {
                const int r = i - table[possible_number[j]];
                const int num = link(possible_number[j] * (int)std::pow(10, zero[r]), dp[r]);

                if (dp[r] == INF)
                {
                    continue;
                }

                // 状态转移方程
                if (dp[i] > num)
                {
                    dp[i] = num;

                    if (possible_number[j] == 0)
                    {
                        zero[i] = zero[r] + 1;
                    }
                    else
                    {
                        zero[i] = 0;
                    }
                }
            }
        }

        int result = INF;

        for (int i = 0; i < len_lists; i ++)
        {
            const int r = n - table[begin_number[i]];
            const int num = link(begin_number[i] * (int)std::pow(10, zero[r]), dp[r]);

            if (dp[r] == INF)
            {
                continue;
            }

            result = std::min(result, num);
        }

        std::cout << ((result >= INF) ? (-1) : (result)) << "\n";
    }
}
2024/10/27 15:17
加载中...