2020 Multi-University Training Contest 6 1005 Fragrant numbers(区间dp)

题目

  http://acm.hdu.edu.cn/showproblem.php?pid=6831

题意

  “1145141919” 的无穷串,给出一个n,要求选最少的num,使得前num个数中间添加任意括号、加号、乘号,计算结果等于n。

题解

  打表知只需前13位就可构造出除了 3 和 7 之外的所有数,所以可以在前 13 位做区间dp即可。注意初始化应将所有一开始可能的数字组合都预先放好。

  dp[i][j][k1 + k2] = dp[i][mid][k1] & dp[mid + 1][j][k2]

  dp[i][j][k1 * k2] = dp[i][mid][k1] & dp[mid + 1][j][k2]

#include <bits/stdc++.h>
// #include <iostream>
// #include <cstring>
// #include <string>
// #include <algorithm>
// #include <cmath>
// #include <cstdio>
// #include <queue>
// #include <stack>
// #include <map>
// #include <bitset>
// #include <set>
// #include <vector>
// #include <iomanip>
#define ll long long
#define ull unsigned long long
#define met(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define bep(i, a, b) for(int i = a; i >= b; --i)
#define lowbit(x) (x&(-x))
#define MID (l + r) / 2
#define ls pos*2
#define rs pos*2+1
#define pb push_back
#define ios() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)

using namespace std;

const int maxn = 1e5 + 1010;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);

int dp[14][14][5010];
int ans[5010];

string str = "*11451419191145";

int main() {
    rep(i, 1, 13) {
        int sum = 0;
        rep(j, i, 13) {
            sum = sum*10 + str[j] - '0';
            if(sum > 5000) break;
            dp[i][j][sum] = 1;
        }
    }
    rep(len, 2, 13) {
        rep(i, 1, 13 - len + 1) {
            int j = i + len - 1;
            rep(mid, i, j - 1) {
                rep(k1, 1, 5000) {
                    if(!dp[i][mid][k1]) continue;
                    rep(k2, 1, 5000) {
                        if(!dp[mid + 1][j][k2]) continue;
                        if(k1 + k2 <= 5000) dp[i][j][k1 + k2] = 1;
                        if(k1 * k2 <= 5000) dp[i][j][k1 * k2] = 1;
                    }
                } 
            }
        }
    }   
    rep(i, 1, 13) {
        rep(j, 1, 5000) {
            if(dp[1][i][j] && !ans[j]) ans[j] = i;
        }
    } 
    int T;
    scanf("%d", &T);
    while(T--) {
        int n;
        scanf("%d", &n);
        printf("%d
", ans[n] == 0 ? -1 : ans[n]);
    }
    return 0;
}

/*

*/
原文地址:https://www.cnblogs.com/Ruby-Z/p/13457810.html