1. 程式人生 > 實用技巧 >2020 Multi-University Training Contest 6 1005 Fragrant numbers(區間dp)

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\n", ans[n] == 0 ? -1 : ans[n]); } return 0; } /* */