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 }