题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=6223
题目:
题意:
给你一个长度为n的数字串,开始时你选择一个位置(记为i,下标从0开始)做为起点,那么下一步将在(i × i + 1)%n处,将字典序最大的路径上的数打印出来。
思路:
要想字典序最大,那么只需每一步都是最大的即可。由题意可知,当起点确定时,所对应的数也就确定了。对于每一步,我们只需当前为最优即可,若第i步有t种方式使得当前数为x,那么下一步也将会有t种选择,那么我们可以用优先队列维护下一步的最优值(具体看代码。这题不加剪枝会T,由于操作中有取膜操作,那么对于同一步,取膜后的下一个位置极有可能会相同,也就是同一个位置重复入队列,这样后面的步骤都会重复,这样复杂度将会增大数倍,此时我们可以用一个set去重,防止同一步重复入队列。
代码实现如下:
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <ctime> 5 #include <stack> 6 #include <cmath> 7 #include <queue> 8 #include <string> 9 #include <cstdio> 10 #include <vector> 11 #include <iomanip> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 using namespace std; 16 17 typedef long long LL; 18 typedef pair<LL, LL> pll; 19 typedef pair<LL, int> pli; 20 typedef pair<int, int> pii; 21 typedef unsigned long long uLL; 22 23 #define lson rt<<1 24 #define rson rt<<1|1 25 #define name2str(name)(#name) 26 #define bug printf("********** "); 27 #define IO ios::sync_with_stdio(false); 28 #define debug(x) cout<<#x<<"=["<<x<<"]"<<endl; 29 #define FIN freopen("/home/dillonh/code/OJ/in.txt","r",stdin); 30 31 const double eps = 1e-8; 32 const int mod = 1e9 + 7; 33 const int maxn = 2000000 + 7; 34 const int inf = 0x3f3f3f3f; 35 const double pi = acos(-1.0); 36 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 37 38 int T, n; 39 int t[maxn]; 40 char s[maxn]; 41 42 struct node { 43 int id, val, step; 44 bool operator < (const node& x) const { 45 return step == x.step ? val < x.val : step > x.step; 46 } 47 }nw, nxt; 48 49 set<int> stc; 50 priority_queue<node> q; 51 52 void bfs() { 53 stc.clear(); 54 while(!q.empty()) q.pop(); 55 int mx = -1; 56 for(int i = 0; i < n; i++) { 57 if(s[i] - '0' > mx) mx = max(mx, s[i] - '0'); 58 } 59 for(int i = 0; i < n; i++) { //将可能的起点压入队列中 60 if(s[i] - '0' == mx) { 61 nw.id = i; 62 nw.val = mx; 63 nw.step = 0; 64 q.push(nw); 65 } 66 } 67 int pp = 0; 68 while(!q.empty()) { 69 nw = q.top(); q.pop(); 70 if(nw.step >= n) return; //满足条件即可返回 71 if(nw.step == pp + 1) { 72 stc.clear(); //到了新的一步需将set清空 73 mx = nw.val; 74 pp = nw.step; 75 } 76 if(nw.val == mx) { 77 t[nw.step] = nw.val; 78 nxt.id = (1LL * nw.id * nw.id + 1) % n; 79 if(stc.count(nxt.id)) continue; //这个位置已经被压入过队列就不需要重复压入了 80 stc.insert(nxt.id); 81 nxt.val = s[nxt.id] - '0'; 82 nxt.step = nw.step + 1; 83 q.push(nxt); 84 } 85 } 86 } 87 88 int main() { 89 #ifndef ONLINE_JUDGE 90 FIN; 91 #endif 92 scanf("%d", &T); 93 for(int icase = 1; icase <= T; icase++) { 94 scanf("%d", &n); 95 scanf("%s", s); 96 bfs(); 97 printf("Case #%d: ", icase); 98 for(int i = 0; i < n; i++) { 99 printf("%d", t[i]); 100 } 101 printf(" "); 102 #ifndef ONLINE_JUDGE 103 cout <<"It costs " <<clock() <<"ms "; 104 #endif 105 } 106 return 0; 107 }