很明显的状态转移问题,这类问题利用bfs求最短路径都能得到有效的解决,基本都是体力活了。
思考一: 如何得到每一个状态的下一个状态
Solution: 这个问题不难,我采用两个函数来进行对第i个位置向上或向下调整。
char* turnup(char*pop,int i){
if(pop[i] == '9') pop[i] = '0';
else pop[i]++;
return pop;
}将第i位加一
char* turndown(char* pop,int i){
if(pop[i] == '0') pop[i] = '9';
else pop[i]--;
return pop;
}将第i位减一
思考二:“1002”与“1000”都能到达“1001”,我们如何避免这样的重复?
Solution: 避免重复我最常用的便是利用哈希表。我们可以将字符串转换成整数,再利用哈希表判断是否出现过。
bool appear(char* pop,int* hash){
int i, val = 0;
for(i = 0;i < 4;i++){
val = val*10 + (pop[i] - '0');
}
if(hash[val] == 0) return false;
else return true;
}//判断pop字符串是否已经遍历过了
思考三: 我们如何判断死亡数字
Solution: 还是利用hash,因为C语言对字符串的去重必须自己动手(没有set QAQ),还有我自己写的去重程序在自己的编译器上好好的,但是在领扣上各种越界,最神奇的是,我不知道为什么target和deadends[0]的size都是8(这里我搞了一整个早上,还是没搞懂)
for(i = 0;i < deadendsSize;i++){
for(k = 0;k <4 ;k++){
val = val*10 + (deadends[i][k] - '0'); }
if(val == 0) return -1;//生来不见天日。
hash[val] = 1;val = 0;
}//判断死亡数字,还有去重的效果哦,真的好用!
下面我们开始实现整个过程:
创建:
int i, j, k, end = 0, ans = 0, endnext = 0, val = 0;
char** queue = (char**)malloc(sizeof(char*));
char** queuenext = (char**)malloc(sizeof(char*));
queue[0] = (char*)malloc(sizeof(char)*5);
char* pop = (char*)malloc(sizeof(char)*5);
strcpy(queue[end++],"0000");
int* hash = (int*)malloc(sizeof(int)*10000);
memset(hash,0,sizeof(int)*10000);
hash[0] = 1;//判断死亡数字见上(这里略了)。
BFS过程
while(end > 0){
for(i = 0;i < end;i++){
if(strcmp(queue[i],target) == 0) return ans;
} //发现目标,游戏结束。
ans++; //没能发现,进入下一层遍历。
for(i = 0;i < end;i++){
strcpy(pop,queue[i]); //出队(本层)
for(j = 0; j < 4;j++){
pop = turnup(pop,j);
if(appear(pop,hash)) pop = turndown(pop,j); //判断是否锁住或遍历过
else{
queuenext = (char**)realloc(queuenext,sizeof(char*)*(endnext+1));
queuenext[endnext++] = (char*)malloc(sizeof(char)*8);
strcpy(queuenext[endnext-1],pop);
for(k = 0;k < 4 ;k++){
val = val*10 + (pop[k] - '0'); }
hash[val] = 1;val = 0;
pop = turndown(pop,j);
}
pop = turndown(pop,j);
if(appear(pop,hash)) pop = turnup(pop,j);
else{
queuenext = (char**)realloc(queuenext,sizeof(char*)*(endnext+1));
queuenext[endnext++] = (char*)malloc(sizeof(char)*5);
strcpy(queuenext[endnext-1],pop);
for(k = 0;k <4 ;k++){
val = val*10 + (pop[k] - '0'); }
hash[val] = 1;val = 0;
pop = turnup(pop,j);
}
}
} //入队(下一层)
end = endnext;
endnext = 0;
queue = (char**)realloc(queue,sizeof(char*)*end);
for(i = 0 ;i < end;i++){
queue[i] = (char*)malloc(sizeof(char)*5);
strcpy(queue[i],queuenext[i]);
}//复制下一层的信息。
}
return -1; //死亡,游戏结束。
}
状态转移问题:商人过河,分酒问题。
BFS学习: 二叉树的层次遍历。