ZOJ 3596Digit Number(BFS+DP)

一道比较不错的BFS+DP题目

题意很简单,就是问一个刚好包含m(m<=10)个不同数字的n的最小倍数。

很明显如果直接枚举每一位是什么这样的话显然复杂度是没有上限的,所以需要找到一个状态表示方法:

令F[i][j] 表示已经用了 i (二进制压位表示)用了 i 这些数字,且余数j为的状态,枚举时直接枚举当前位,那么答案明显就是F[m][0]

我这里将状态i, j存在了一维空间里,即 i * 1000 + j表示,实际上用一个结构体存队列里的点,用二维数组标记状态也是可行的。

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf (-((LL)1<<40))
 17 #define lson k<<1, L, mid
 18 #define rson k<<1|1, mid+1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FIN freopen("in.txt", "r", stdin)
 23 #define FOUT freopen("out.txt", "w", stdout)
 24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
 25
 26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
 27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
 28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 32
 33 //typedef __int64 LL;
 34 typedef long long LL;
 35 const int MAXN = 110000;
 36 const int MAXM = 20010;
 37 const double eps = 1e-4;
 38 //LL MOD = 987654321;
 39
 40 int t, n, m, x;
 41 struct Node {
 42     bool vis;
 43     char num;
 44     int pre, cnt;
 45 }s[(1<<10) * 1100];
 46 char ans[110000], d[110000];
 47
 48 int bfs()
 49 {
 50     queue<int>q;
 51     q.push(0);
 52     while(!q.empty()) {
 53         int head = q.front();q.pop();
 54         rep (i, 0, 9) {
 55             if(head == 0 && i == 0) continue;
 56             int mod = (head % 1000 * 10 + i) % n;
 57             int tail = ((head / 1000) | (1 << i)) * 1000 + mod;
 58             if(s[tail].vis)
 59                 continue;
 60             s[tail].vis = true;
 61             s[tail].num = i + ‘0‘;
 62             s[tail].pre = head;
 63             s[tail].cnt = s[head].cnt + ((head / 1000) & (1 << i) ? 0 : 1);
 64             if(s[tail].cnt == m && mod == 0) {
 65                 return tail;
 66             }
 67             if(s[tail].cnt <= m) q.push(tail);
 68         }
 69     }
 70     return 0;
 71 }
 72
 73 //calc a / b
 74 char* divide(char *a, int len, int b) {
 75     mem0(d);
 76     int i = 0, cur = 0, l = 0;
 77     while(cur < b && i < len) {
 78         cur = cur * 10 + a[i++] - ‘0‘;
 79     }
 80     d[l++] = cur / b + ‘0‘;
 81     while(i < len) {
 82         cur = cur % b * 10 + a[i++] - ‘0‘;
 83         d[l++] = cur / b + ‘0‘;
 84     }
 85     return d;
 86 }
 87
 88 void print(int ed) {
 89     int len = 0;
 90     mem0(ans);
 91     while(ed) {
 92         ans[len++] = s[ed].num;
 93         ed = s[ed].pre;
 94     }
 95     reverse(ans, ans + len);
 96     printf("%s=%d*%s\n", ans, n, divide(ans, len, n));
 97 }
 98
 99 int main()
100 {
101     //FIN;
102     while(cin >> t) while(t--) {
103         cin >> n >> m;
104         mem0(s);
105         if( !(x = bfs()) ) {
106             puts("Impossible");
107         }
108         else {
109             print(x);
110         }
111     }
112     return 0;
113 }
时间: 2024-10-07 13:36:09

ZOJ 3596Digit Number(BFS+DP)的相关文章

ZOJ 3551 Bloodsucker (概率DP)

ZOJ Problem Set - 3551 Bloodsucker Time Limit: 2 Seconds      Memory Limit: 65536 KB In 0th day, there are n-1 people and 1 bloodsucker. Every day, two and only two of them meet. Nothing will happen if they are of the same species, that is, a people

Balanced Number (数位dp)

Balanced Number Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box wit

hdu 3709 Balanced Number (数位dp)

Balanced Number Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 1871    Accepted Submission(s): 836 Problem Description A balanced number is a non-negative integer that can be balanced if a pi

SPOJ MYQ10 10649. Mirror Number (数位dp)

SPOJ MYQ10 10649. Mirror Number (数位dp) ACM 题目地址:SPOJ MYQ10 Mirror Number 题意: 求[a,b]中镜像回文的个数. 0 <= a<=b <= 10^44 分析: 看到题目和数据范围就知道是数位dp了. 很明显镜像回文只有0,1,8,跟回文的一题一样,在dfs的时候得开个辅助数组记录前面已经选择的数字. 注意还得去掉前导0. 代码: /* * Author: illuz <iilluzen[at]gmail.com

HDU 3565 Bi-peak Number(数位DP)题解

题意:我们定义每一位先严格递增(第一位不为0)后严格递减的数为峰(比如1231),一个数由两个峰组成称为双峰,一个双峰的价值为每一位位数和,问L~R双峰最大价值 思路:数位DP.显然这个问题和pos有关,和前一项有关,和当前状态有关,我们定义dp[i][j][k]第i位前面j状态k的后面的最佳情况. 状态有7种: 0什么都没,1刚开始第一个上坡,2已经第一个上坡了可以转折了,3第一个下坡04刚开始第二个上坡,5已经第二个上坡可以转折了,6第二个下坡 然后数位DP一下就好了. 注意,要开ull,3

【2019.8.14 慈溪模拟赛 T1】我不是!我没有!别瞎说啊!(notme)(BFS+DP)

\(IDA^*\) 说实话,这道题我一开始没想出正解,于是写了一个\(IDA^*\)... 但神奇的是,这个\(IDA^*\)居然连字符串长度分别为\(2500,4000\)的数据都跑得飞快,不过数据发下来之后我测了一下只有45分. 就在不断优化\(IDA^*\)的过程中,我突然就想出了正解的做法,看来以后遇事不决先暴力. \(DP\)求解第一个询问 考虑一个\(DP\),我们设\(f_{i,j}\)表示当前在第一个字符串中是第\(i\)位,第二个字符串中是第\(j\)位的最小步数. 若记录\(

ZOJ 3822 Domination (概率DP)

Domination Time Limit: 8 Seconds      Memory Limit: 131072 KB      Special Judge Edward is the headmaster of Marjar University. He is enthusiastic about chess and often plays chess with his friends. What's more, he bought a large decorative chessboar

ZOJ 3805 Machine(简单dp)

Machine Time Limit: 2 Seconds      Memory Limit: 65536 KB In a typical assembly line, machines are connected one by one. The first machine's output product will be the second machine's raw material. To simplify the problem, we put all machines into a

ZOJ 3689 Digging(贪心+dp)

Digging Time Limit: 2 Seconds      Memory Limit: 65536 KB When it comes to the Maya Civilization, we can quickly remind of a term called the end of the world. It's not difficult to understand why we choose to believe the prophecy (or we just assume i