hdu2553(详细注释加dfs模板)

这题好像是第一次接触dfs,所以注释很详细了。
再贴个老师的模板吧,初次接触我感觉看看模板挺有用的
在这里插入图片描述

在这里插入图片描述
模板注意事项在这里插入图片描述当然还原也不是必须的步骤,要自己去看题意还需不需要你访问访问过的地方,如果需要就不用还原了。
题解

/*本题要打表记录每种可能,不然每dfs一次算一次会超时,打表法应用*/
#include <iostream>
#include <stdio.h>
#include <cstring>//memset函数头文件
#include <cmath>
const int maxn = 11;
int map[maxn];//需要注意的是map[k]=j。表示的是第k个棋子放在第j列.
/*k为第几个棋子,j为第几个棋子放的列数*/
int visited[maxn];//用於标记某一列是否已经访问过
int result[maxn];//打表,保存各个结果
int flag;
int ans;
int n;
using namespace std;
void dfs(int k) {

	if (k == n + 1) {//如果k已经达到n+1.表示所有棋子已经摆放完毕

		ans++;//棋子成功拜访的方案数+1

		return;

	}



	int i;

	int j;

	for (i = 1; i <= n; ++i) {//遍历所有列

		if (visited[i] == false) {//如果该列没有被访问

			map[k] = i;//尝试将第k个棋子放在第i列(第k个旗子肯定是在第k行的)

			flag = true;//置尝试标记为成功

			for (j = 1; j <= k - 1; ++j) {//遍历之前的k-1个棋子

				/**

				 * 如果他们在同一斜线上(在这种实现方式中,他已经确保了没一个棋子肯定会与其他棋子在不同行、不同列.

				 * 这时候我们只需要判断一下它们是否在同一斜线上即可)

				 */

				if (abs(map[k] - map[j]) == abs(k - j)) {

					flag = false;//将标记设置为false

					break;/*换下一列*/

				}



			}



			if (flag == 1) {//如果flag为true,表示第k个棋子可以摆放成功

				visited[i] = 1;//将第i列标记为已经访问过

				dfs(k + 1);//开始拜访第k+1棋子

				visited[i] = 0;//将第i列重新标记为未访问过.用于其他情况

			}

		}

	}

}



int main()
{
    while(scanf("%d",&n)!=EOF)
    {   memset(visited,0,sizeof(visited));
        flag=0;
        ans=0;
        if(n==0)
        break;

        dfs(1);
        printf("%d\n",ans);
    }
    return 0;
}
发布了30 篇原创文章 · 获赞 5 · 访问量 6948

猜你喜欢

转载自blog.csdn.net/weixin_44735312/article/details/90942477