题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=6223
题目大意:
给你一个n位的数字串,第i位可以跳到第(i*i+1)的位子上;
让你从这个数字串的任何位置跳n次;
求能跳的最大数字;
n最多一万位;
思路
BFS
先找最大的一位/几位作为头结点;
然后BFS;
剪枝1:现在搜的数不可能比答案大了
剪枝2:当前层访问过了;
上代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
/*------------------------------------------------------------------------------*/
struct node{
int num,wz,clock;
node(){}
node(int num,int wz,int clock):num(num),wz(wz),clock(clock){}
// 为了下面赋值方便所以这样打
};
int T,t,i,n,da;
char st[150010];
int a[150010],next[150010],ans[150010],bfn[150010];
// ans[]存放答案;
// bfn[]表示访问时间,或者可以当成时间戳,在答案的第几位,搜索的第几层;
// 这是本代码精彩之处;
struct cmp{
bool operator()(node a,node b)
{
if(a.clock!=b.clock) return a.clock>b.clock;
else if(a.num!=b.num) return a.num<b.num;
return a.wz>b.wz;
}
}; // 向后移动的条件;
// 放在前面的数:时间短的,数字大的,在前面的
// 优先队列+BFS的题目还真是第一次做
priority_queue<node,vector<node>,cmp> q;
/*------------------------------------------------------------------------------*/
void BFS()
{
memset(bfn,-1,sizeof(bfn));
memset(ans,-1,sizeof(ans));
while(!q.empty())
{
node t=q.top();
q.pop();
if(ans[t.clock]==-1) ans[t.clock]=t.num;
if(ans[t.clock]>t.num) continue; //剪枝1,小的
if(bfn[t.wz]<t.clock) bfn[t.wz]=t.clock; // 剪枝2,慢的
else continue;
if (t.clock==n-1) continue;
q.push(node(a[next[t.wz]],next[t.wz],t.clock+1));
}
cout<<"Case #"<<t<<": ";
for (int j=0; j<n; j++) printf("%d",ans[j]); cout<<endl;
}
/*------------------------------------------------------------------------------*/
int main()
{
scanf("%d",&T);
for (t=1; t<=T; t++)
{
scanf("%d\n",&n);
gets(st);
da=0;
for (i=0; i<strlen(st); i++)
{
a[i]=st[i]-'0';
if (a[i]>da) da=a[i];
next[i]=(((ll)i*(ll)i+1)%(ll)n);
} //寻找第一个起始位置
for (i=0; i<n; i++) if (a[i]==da){
node temp; temp.num=a[i],temp.wz=i,temp.clock=0;
q.push(temp);
} // 入队
BFS();
}
}