大体题意:
给你n个字符串(长度为2),表示这些字符串不准出现在矩阵中,让你构造一个尽可能大的字符矩阵,如果大小超过了20×20,那么就输出20×20的即可,否则输出你构造的矩阵?
吐槽:
真是服气了,忘记了回溯,改了一晚上= =!(好弱)
思路:
字符串的长度始终是2,很明显是一个图的题目,且出现的字符串是禁止使用的,因此我们可以给g[][]数组初始化-1,输入一个变成0即可!
然后在剩下的图中,如果存在有向环的话,肯定是可以无限输出的!
否则就找出一条最长的通路,长度为lenp,那么矩阵的大小边 就是 (lenp + 1 )/2.
上述结论分析以下便知!
然后既是dfs了,记得回溯vis数组即可!
大体说下dfs写法:
枚举起点,判断是否能以起点开始找到以起点结束的环,如果能直接return 1了,否则就找出最大通路 return 0!
详细见代码:
注意:
memcpy 中sizeof 是第一个数组的,否则内存溢出!
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 30;
char cmd[maxn];
int vis[maxn];
int g[maxn][maxn];
int path[maxn<<5];
int ans[maxn<<2];
int lenp;
bool circle = 0;
int dfs(int u,int cur,int s){
if (circle)return 1;
vis[u] = 1;
bool ok = 0;
if (g[u][s] && vis[s]){
path[cur] = u;
lenp = cur;
circle = 1;
memcpy(ans,path,sizeof ans);
return 1;
}
for (int i = 0; i < 26; ++i){
if (g[u][i] && !vis[i]){
ok = 1;
path[cur] = i;
if (dfs(i,cur+1,s))return 1;
vis[i] = 0;
}
}
if (!ok){
if (cur > lenp){
memcpy(ans,path,sizeof ans);
lenp = cur;
}
}
return false;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
circle = 0;
scanf("%d",&n);
lenp = 0;
memset(g,-1,sizeof g);
for (int i = 0; i < n; ++i){
scanf("%s",cmd);
g[cmd[0]-'a'][cmd[1]-'a'] = 0;
}
for (int i = 0; i < 26; ++i){
memset(vis,0,sizeof vis);
path[0] = i;
if (dfs(i,1,i))break;
}
if (circle){
for (int i = 0; i < 20; ++i){
int s = i % lenp;
for (int j = 0; j < 20; ++j){
printf("%c",ans[(s+j)%lenp] + 'a');
}
puts("");
}
}
else {
int n = lenp + 1 >> 1;
for (int i = 0; i < n; ++i){
int s = i;
for (int j = 0; j < n; ++j){
printf("%c",ans[s+j] + 'a');
}
puts("");
}
}
}
return 0;
}
/**
100
3
ab
bc
ca
4
ab
bc
cd
ad
5
ab
bc
ca
cd
ad
**/