图案解锁是智能手机一项常用的功能。你需要在3x3的点阵上,从任意一个点开始,反复移动到一个尚未经过的"相邻"的点。这些划过的点所组成的有向折线,如果与预设的折线在图案、方向上都一致,那么手机将解锁。两个点相邻当且仅当以这两个点为端点的线段上不存在尚未经过的点。此外,这条折线还需要至少经过4个点。
有些人可能有和我一样的疑问,在这小小的9个点中,图案密码总共有多少种形式呢?今天我就使用深度优先搜索的方法解决这个问题。具体c++代码如下:
#include<iostream> using namespace std; int isvisit[10]={0};//表示当前该点是否在路径中 int noPath[8][3]={{1,3,2},{4,6,5},{7,9,8},{1,7,4},{2,8,5},{3,9,6},{1,9,5},{3,7,5}};//每项的三个数字{a,b,c}表示:当点c未在路径上时,<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;">点a和点b不能直接相连</span> int j,k;
int hasPath(int start,int end)//判断此时两点是否可以直接相连 { for(j=0;j<8;j++) { if( (start==noPath[j][0]&&end==noPath[j][1]) || (start==noPath[j][1]&&end==noPath[j][0]) ) { if(isvisit[ noPath[j][2] ])<span style="white-space:pre"> </span>//表示点c已经在路径上,a和b直接可以直接连接 return 1; else return 0; } } return 1; } int dfs(int start,int length) { int count = 0; isvisit[start]=1; int i; for(i=1;i<10;i++)<span style="white-space:pre"> </span>//遍历所有为访问的点 { if(i==start || isvisit[i]) continue; if(hasPath(start,i)) { count += dfs(i,length+1);<span style="white-space:pre"> </span>//递归搜索 } } isvisit[start]=0; if(length>=4)<span style="white-space:pre"> </span>//如果路径长度超过4,则该路径符合要求 count++; return count; } int main() { int result=0; for(k=1;k<10;k++)<span style="white-space:pre"> </span>//分别从9个点开始dfs,为提升效率,此处可以根据对称原则减少不必要的运算 result+=dfs(k,1); cout << result << endl; return 0; }
运算结果为:389112
时间: 2024-10-16 09:18:47