题意:
给定一个数字串,每个位子都能向(i*i+1)%n的位子转移,输出路径上,字典序最大的,长度为n的串。
参考:https://www.cnblogs.com/mountaink/p/9541442.html
思路:
BFS,
一个数字肯定是最高位越大,这个数字本身就越大,所以肯定第一位要取最大值,在这一位取最大值的时候后面每一位都要尽量最大,所以想到bfs。
但是bfs肯定要剪枝,怎么剪枝呢?
1、按照思路,我要取每一位尽可能大的值,所以某一个状态的某一位小于我当前以及有的解,这个状态肯定被舍弃。
这是最好想的思路,但是如果对于一个全是9的数列,这个剪枝完全没有用,所以必须有其他的剪枝。
2、如果到了从不同起点到达某一个位置,在答案数列中的层次是一样的,舍弃掉。(换句话说,不同起点经过相同步数到达同一座城市,那么后续的状态都是一样的了,所以没必要再走下去),
具体怎么实现呢,一开始将数列中所有最大值所在的位置入队,对于某一种状态,看他的下一步是否比答案中更优或者相等(答案数组初始化为-1),如果更优或者相等则重新入队。 对于新状态,先检查一下当前位置的值是不是和答案数组中当前位置的最大值相等,如果不相等,舍弃,如果相等,判断一下有没有状态在相同步数的情况下已经走到这一步了,有则舍弃,没有则更新一下,然后重复上述操作。
// #pragma GCC optimize(3) // #pragma comment(linker, "/STACK:102400000,102400000") //c++ // #pragma GCC diagnostic error "-std=c++11" // #pragma comment(linker, "/stack:200000000") // #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> using namespace std; #define lson (l , mid , rt << 1) #define rson (mid + 1 , r , rt << 1 | 1) #define debug(x) cerr << #x << " = " << x << "\n"; #define pb push_back #define pq priority_queue typedef long long ll; typedef unsigned long long ull; //typedef __int128 bll; typedef pair<ll ,ll > pll; typedef pair<int ,int > pii; typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q //priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q #define fi first #define se second //#define endl ‘\n‘ #define OKC ios::sync_with_stdio(false);cin.tie(0) #define FT(A,B,C) for(int A=B;A <= C;++A) //用来压行 #define REP(i , j , k) for(int i = j ; i < k ; ++i) #define max3(a,b,c) max(max(a,b), c); //priority_queue<int ,vector<int>, greater<int> >que; const ll mos = 0x7FFFFFFF; //2147483647 const ll nmos = 0x80000000; //-2147483648 const int inf = 0x7f7f7f7f; const ll inff = 0x3f3f3f3f3f3f3f3f; //18 const int mod = 1e8+7; const double esp = 1e-8; const double PI=acos(-1.0); const double PHI=0.61803399; //黄金分割点 const double tPHI=0.38196601; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<‘0‘||ch>‘9‘) f|=(ch==‘-‘),ch=getchar(); while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x=f?-x:x; } /*-----------------------showtime----------------------*/ const int maxn = 150009; int d[maxn],n; char str[maxn]; struct node { ll u,cur,pos; node(){} node(int u,int pos ,int cur):u(u),pos(pos),cur(cur){} }; queue<node> q;//这是一个大根堆q int dep[maxn],vis[maxn]; int main(){ int T; scanf("%d", &T); for(int tt=1; tt<=T; tt++){ scanf("%d%s", &n, str); // memset(dep, -1, sizeof(dep)); // memset(vis, -1, sizeof(vis)); int mx = 0; for(int i=0; i<n; i++) d[i] = (int)(str[i] - ‘0‘), mx = max(mx, d[i]); memset(vis,-1,sizeof(vis)); memset(dep,-1,sizeof(dep)); for(int i=0; i<n; i++) if(d[i] == mx) q.push(node(d[i], i, 0)); while(!q.empty()){ node tmp = q.front(); q.pop(); if(tmp.cur == n)break; //第n个确定 if(dep[tmp.cur] > tmp.u)continue; else if(dep[tmp.cur] == tmp.u && vis[tmp.pos] == tmp.cur)continue; //同一个pos,第二次来 else { dep[tmp.cur] = tmp.u; vis[tmp.pos] = tmp.cur; ll nx = (1ll*tmp.pos * tmp.pos + 1ll)%(1ll*n); // if(tmp.cur==n-1)break; dep[tmp.cur+1] = max(dep[tmp.cur+1] ,d[nx]); q.push(node(d[nx], nx, tmp.cur+1)); } } while(!q.empty())q.pop(); printf("Case #%d: ", tt); for(int i=0; i<n; i++) printf("%d", dep[i]); printf("\n"); } return 0; }
HDU 6223
原文地址:https://www.cnblogs.com/ckxkexing/p/9934540.html
时间: 2024-11-09 03:58:04