题目大意是有一个DIMA四种字母组成的矩阵,要在矩阵中找最长的DIMADIMADIMA……串,连接方式为四方向连接,问最长能找到多少DIMA。字母可以重复访问,如果DIMA串成环,即可以取出无限长的DIMA串,则输出特定字符串,若没有DIMA串,也输出另一特定字符串,否则输出最长多少DIMA串。
这是我大一暑假的时候做的,并且当时WA在第23组上,后来就没继续做这个题了,现在不想看大一的代码了。
重新想了一下,其实就是判图中是否有环,无环的话,DIMA的链最长多少,也就是找图中以D字母开头的最长链。
那么读入之后对D->I I->M M->A A->D 进行建边,并判环以及求最长链即可。
我考虑判环和求最长链长度都可以通过DFS实现,所以就只写了一个DFS函数。
DFS当然是没有写错的,但是发现在第10组T了。想了一下,DFS总复杂度是O(n^2+m)的,m为边数,因为所有点和边都只会被DFS一次,我全部从D字母开始搜索。此时因为我判环有提前return的操作,会导致vis没有清空,因此我在每次DFS前有memset掉vis数组的操作。如果D特别多,则memset每次都是O(n^2)的复杂度,就会超时。我修改了一下,将DFS过程中的return前都将vis置为0,就不用memset了,于是就过了。
其实如果将判环和求最长链分开,或许就不会出现这样的问题,比如用拓扑序判环,肯定不会出现大量memset。判完环再求最长链,则已经知道图中没有环,DFS每个点必定只需要访问一次,就不需要memset了。
1 #include <bits/stdc++.h>
2 using namespace std;
3 #define PB push_back
4 #define MP make_pair
5 typedef long long ll;
6 const int mod = 1e9 + 7;
7 const int INF = 0x3f3f3f3f;
8 const double eps = 1e-8;
9 const int maxn = 1e6 + 5;
10
11 int n,m;
12 int xx[4] = {1,-1,0,0};
13 int yy[4] = {0,0,1,-1};
14 char s[1005][1005];
15 int id[1005][1005];
16 int dis[maxn];
17 int head[maxn],point[maxn<<2],nxt[maxn<<2],size;
18 int vis[maxn];
19 bool flag = false;
20
21 void init(){
22 size = 0;
23 memset(head,-1,sizeof(head));
24 memset(dis,0,sizeof(dis));
25 memset(vis,0,sizeof(vis));
26 flag = false;
27 }
28
29 void add(int a, int b){
30 point[size] = b;
31 nxt[size] = head[a];
32 head[a] = size++;
33 }
34
35 void dfs(int s){
36 if(dis[s])return;
37 vis[s] = 1;
38 dis[s] = 1;
39 for(int i = head[s] ; ~ i ; i = nxt[i]){
40 int j = point[i];
41 if(vis[j]){flag = true;vis[s] = 0;return;}
42 dfs(j);
43 if(flag){vis[s] = 0;return;}
44 dis[s] = max(dis[s],dis[j]+1);
45 }
46 vis[s] = 0;
47 }
48
49 int main(){
50 scanf("%d%d",&n,&m);
51 for(int i = 1 ; i <= n ; ++ i)scanf("%s",s[i]+1);
52 int cnt = 0;
53 for(int i = 1 ; i <= n ; ++ i){
54 for(int j = 1 ; j <= m ; ++ j){
55 id[i][j] = ++ cnt;
56 }
57 }
58 init();
59 for(int i = 1 ; i <= n ; ++ i){
60 for(int j = 1 ; j <= m ; ++ j){
61 for(int k = 0 ; k < 4 ; ++ k){
62 int dx = i + xx[k];
63 int dy = j + yy[k];
64 if(dx < 1 || dx > n || dy < 1 || dy > m)continue;
65 if(s[i][j] == 'D' && s[dx][dy] == 'I')add(id[i][j],id[dx][dy]);
66 if(s[i][j] == 'I' && s[dx][dy] == 'M')add(id[i][j],id[dx][dy]);
67 if(s[i][j] == 'M' && s[dx][dy] == 'A')add(id[i][j],id[dx][dy]);
68 if(s[i][j] == 'A' && s[dx][dy] == 'D')add(id[i][j],id[dx][dy]);
69 }
70 }
71 }
72 int ans = 0;
73 for(int i = 1 ; i <= n ; ++ i){
74 for(int j = 1 ; j <= m ; ++ j){
75 if(s[i][j] != 'D')continue;
76 dfs(id[i][j]);
77 if(flag == true){
78 printf("Poor Inna!\n");
79 return 0;
80 }
81 if(dis[id[i][j]] > ans)ans = dis[id[i][j]];
82 }
83 }
84 ans /= 4;
85 if(ans)printf("%d\n",ans);
86 else printf("Poor Dima!\n");
87 return 0;
88 }