Infinite Fraction Path
优先队列BFS + 剪枝
思路都在注释里
// reference: https://www.cnblogs.com/stranger-/p/7841085.html
// BFS + 剪枝,略抽象
#include <bits/stdc++.h>
#define MAX 150005
using namespace std;
int n, m; // n是题目里的N
int dst[MAX]; // 每个城市的终点
int val[MAX]; // 每个城市对应的0-9的数字
int vis[MAX]; // 记录每个点被访问的情况
int ans[MAX]; // 记录答案
char str[MAX];
struct node
{
int val, pos, ans; // val数组中对应的值,下标,ans数组的下标
node(int val, int pos, int ans)
{
this->val = val;
this->pos = pos;
this->ans = ans;
}
friend bool operator<(node n1, node n2)
{
if (n1.ans != n2.ans)
return n1.ans > n2.ans;
if (n1.val != n2.val)
return n1.val < n2.val;
else
return n1.pos > n2.pos;
}
};
int main()
{
cin.sync_with_stdio(false);
cin.tie(0); // 不一定要关流
int cases;
cin >> cases;
for (int caseCount = 1; caseCount <= cases; ++caseCount)
{
cin >> n;
cin >> str;
m = 0;
for (long long i = 0; i < n; ++i)
{
val[i] = str[i] - '0';
dst[i] = int((i * i + 1) % n); // n最大是150000,平方会爆int,所以i用long long
vis[i] = ans[i] = -1;
m = max(m, val[i]);
}
priority_queue <node> q;
for (int i = 0; i < n; ++i)
{
if (val[i] == m)
q.push(node { m, i, 0 });
}
while (!q.empty())
{
node now = q.top();
q.pop();
if (ans[now.ans] == -1) // 该位置未赋值,赋初值
ans[now.ans] = now.val; // 由于优先队列的排序,所有ans相同的node中,排在最前面的是val最大的,所以只需要
// 一次赋值,剩下的情况都从下面的那个if那里略去了
if (ans[now.ans] > now.val) // 剪枝:已经出现了比当前情况大的情况
continue;
if (vis[now.pos] < now.ans)
vis[now.pos] = now.ans;
else
continue; // 剪枝:当前节点已经被具有相同ans值的其他分支访问过了,后续的结果都是相同的,不重复访问
// 因为ans值小的node在priority_queue中排在前面,不会出现vis[now.pos] > now.ans的情况
if (now.ans == n - 1)
continue; // 已经得出答案
q.push(node { val[dst[now.pos]], dst[now.pos], now.ans + 1 });
}
cout << "Case #" << caseCount << ": ";
for (int i = 0; i < n; ++i)
cout << ans[i];
cout << endl;
}
}