what’s 剪枝?
因为深搜都是指数级别的,只要题目数据那么xiao微一大,直接TLE
所以剪枝的重要性就体现出来力。假设你在一棵树上进行深搜,剪枝此时的意思就是字面意思 通过准确且正确的条件进行剪枝,使程序运行时间大大减小
从上到下
时间限制:1秒 内存限制:128M 小可在玩一个格子游戏。格子游戏的地图是一个大正方形,大正方形被分为了 n×n
个小正方形。小可一开始位于左上角的格子,要走到左下角的格子上去。走格子的路径有一个规则,必须路过所有格子恰好一次。如 n=3
时有两种走法:
现在小可想知道给定 n ,有多少条可行路径
输入描述一行,一个整数 n
输出描述
一行,一个整数,表示可行路径数
输入样例
3
输出样例2
数据范围1<=n<=7
冷静分析:
首先,暴搜看起来异常简单,在一看数据范围似乎确实可以 但细算一下,按上限n=7,此时一共有49个格点,每一个格子有上下左右四种选择——449你猜会不会爆?再多看一眼就会爆炸,毫不犹豫考虑剪枝
剪枝1: 看下面的图 ,走了一圈进了一个死胡同,所以我们的目标就是从死胡同上做文章,but how?
再看下面的图片,当我们走到中间这个白点时,四周的对点是相反的状态
如果我们往右走,死胡同;往左走,右边的死胡同就进不去了,因为题目规定所有点都得遍历一遍,所以遇到这种情况就剪枝得了
剪枝2:
看此图,我们已经走到了点B(然后标记掉),然后点A四周就只有往左的方向没有走过,所以点A只能通过点B走过,所以称点A为点B的必经点
然后如果点B四周出现两个以上的必经点呢?是不是点B只能走其中任意的一个?
那剩下的必经点就变成了三面被标记的死胡同,自然而然就不会产生到达终点的答案
怎么判断一个点是否为必经点?
根据刚才的定义,三面都被标记的点即为必经点,直接计数器++
AC code:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<stack>
#include<map>
#define TIE ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define N 15
#define INF 0x3f3f3f3f
using namespace std;
int n, ans, a[N][N];
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, 1, -1};
int getfree(int x, int y) {
int cnt = 0;
for (int i = 0; i < 4; i++) {
if (a[x + dx[i]][y + dy[i]] == 0)
cnt++;
}
return cnt;
}
void dfs(int x, int y, int step) {
if (x == n && y == 1) {
if (step == n * n) {
ans++;
return;
}
}
if ((a[x][y - 1] && a[x][y + 1] && a[x - 1][y] == 0 && a[x + 1][y] == 0) ||
(a[x][y - 1] == 0 && a[x][y + 1] == 0 && a[x - 1][y] && a[x + 1][y]))
return;
int cntbijing = 0;
int nx, ny;
for (int i = 0; i < 4; i++) {
int xx = x + dx[i], yy = y + dy[i];
if (a[xx][yy] || (xx == n && yy == 1)) continue;
int cnt = getfree(xx, yy);
if (cnt == 1) {
cntbijing++;
nx = xx, ny = yy;
}
}
if (cntbijing > 1)
return;
else {
if (cntbijing == 1) {
a[nx][ny] = 1;
dfs(nx, ny, step + 1);
a[nx][ny] = 0;
} else {
for (int i = 0; i < 4; i++) {
int xx = x + dx[i], yy = y + dy[i];
if (a[xx][yy] == 0) {
a[xx][yy] = 1;
dfs(xx, yy, step + 1);
a[xx][yy] = 0;
}
}
}
}
}
int main() {
TIE;
cin >> n;
for (int i = 0; i <= n + 1; i++) {//设置保护区
a[0][i] = a[n + 1][i] = a[i][0] = a[i][n + 1] = 1;
}
a[1][1] = 1;
dfs(1, 1, 1);
cout << ans;
return 0;
}
完结撒花~~~