hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)

题目传送门

题目大意:给出n座城市,每个城市都有一个0到9的val,城市的编号是从0到n-1,从i位置出发,只能走到(i*i+1)%n这个位置,从任意起点开始,每走一步都会得到一个数字,走n-1步,会得到一个长度为n的数列,输出能得到的最大的数列(当成数字)。

思路:

一个数字肯定是最高位越大,这个数字本身就越大,所以肯定第一位要取最大值,在这一位取最大值的时候后面每一位都要尽量最大,所以想到bfs。

但是bfs肯定要剪枝,怎么剪枝呢?

1、按照思路,我要取每一位尽可能大的值,所以某一个状态的某一位小于我当前以及有的解,这个状态肯定被舍弃。

这是最好想的思路,但是如果对于一个全是9的数列,这个剪枝完全没有用,所以必须有其他的剪枝。

2、如果到了从不同起点到达某一个位置,在答案数列中的层次是一样的,舍弃掉。(换句话说,不同起点经过相同步数到达同一座城市,那么后续的状态都是一样的了,所以没必要再走下去),

具体怎么实现呢,一开始将数列中所有最大值所在的位置入队,对于某一种状态,看他的下一步是否比答案中更优或者相等(答案数组初始化为-1),如果更优或者相等则重新入队。 对于新状态,先检查一下当前位置的值是不是和答案数组中当前位置的最大值相等,如果不相等,舍弃,如果相等,判断一下有没有状态在相同步数的情况下已经走到这一步了,有则舍弃,没有则更新一下,然后重复上述操作。

 1 //hdu6223  249ms
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<string.h>
 7 #include<sstream>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<queue>
12 #include<stack>
13 #include<bitset>
14 #define CLR(a,b) memset(a,b,sizeof(a))
15 using namespace std;
16 typedef long long ll;
17 inline int rd() {
18     int f=1;
19     int x=0;
20     char s=getchar();
21     while(s<'0'||s>'9') {
22         if(s=='-')f=-1;
23         s=getchar();
24     }
25     while(s>='0'&&s<='9') {
26         x=x*10+s-'0';
27         s=getchar();
28     }
29     x*=f;
30     return x;
31 }
32 const int inf=0x3f3f3f3f;
33 const int maxn=250010;
34 int maxx,vis[maxn],tot;
35 char a[maxn],ans[maxn];
36 ll n;
37 struct dian {
38     int step;//步数 
39     ll pos;//在原数组中对应的位置 
40     dian() {}
41     dian(int step,ll pos):step(step),pos(pos) {}
42 };
43 queue<dian >q;
44 inline void bfs() {
45     dian s;
46     while(!q.empty()) {
47         s=q.front();
48         q.pop();
49         if(s.step==n) {//终止条件 
50             continue;
51         }
52         if(a[s.pos]==ans[s.step]) {//如果相等,则代表目前的状态是最优的 
53             if(vis[s.pos]==s.step)continue;//之前已经来到过这个状态 
54             vis[s.pos]=s.step;
55             s.pos= (s.pos * s.pos + 1) % n;
56             s.step++;
57             if(a[s.pos]>=ans[s.step]) {
58                 ans[s.step]=a[s.pos];
59                 q.push(s);
60             }
61         }
62     }
63 }
64 int main() {
65     int T;
66     int cas=1;
67     cin>>T;
68     while(T--) {
69         while(!q.empty())q.pop();
70         tot=0;
71         scanf("%lld",&n);
72         maxx=0;
73         scanf("%s",a);
74         for(int i=0; i<n; i++) {
75             maxx=max(maxx,(int)a[i]);
76         }
77         for(int i=0; i<n; i++) {
78             if(a[i]==maxx) {
79                 q.push(dian(1,i));//最大值入队 
80             }
81         }
82         CLR(ans,-1);
83         CLR(vis,-1);
84         ans[1]=maxx;//第一个位置先更新 
85         bfs();//主要过程 
86         printf("Case #%d: ",cas++);
87         ans[n+1]='\0';
88             printf("%s",ans+1);
89         printf("\n");
90     }
91 }
View Code

写了很久,做了很多细节优化

 

Infinite Fraction Path

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2856    Accepted Submission(s): 576


Problem Description
The ant Welly now dedicates himself to urban infrastructure. He came to the kingdom of numbers and solicited an audience with the king. He recounted how he had built a happy path in the kingdom of happiness. The king affirmed Welly’s talent and hoped that this talent can help him find the best infinite fraction path before the anniversary.
The kingdom has N cities numbered from 0 to N - 1 and you are given an array D[0 ... N - 1] of decimal digits (0 ≤ D[i] ≤ 9, D[i] is an integer). The destination of the only one-way road start from the i-th city is the city labelled (i2 + 1)%N.
A path beginning from the i-th city would pass through the cities u1,u2,u3, and so on consecutively. The path constructs a real number A[i], called the relevant fraction such that the integer part of it is equal to zero and its fractional part is an infinite decimal fraction with digits D[i], D[u1], D[u2], and so on.
The best infinite fraction path is the one with the largest relevant fraction
 

 

Input
The input contains multiple test cases and the first line provides an integer up to 100 indicating to the total numberof test cases.
For each test case, the first line contains the integer N (1 ≤ N ≤ 150000). The second line contains an array ofdigits D, given without spaces.
The summation of N is smaller than 2000000.
 

 

Output
For each test case, you should output the label of the case first. Then you are to output exactly N characters which are the first N digits of the fractional part of the largest relevant fraction.
 

 

Sample Input
4 3 149 5 12345 7 3214567 9 261025520
 

 

Sample Output
Case #1: 999 Case #2: 53123 Case #3: 7166666 Case #4: 615015015

 

posted @ 2018-08-27 12:07  光芒万丈小太阳  阅读(942)  评论(0编辑  收藏  举报