#include<stdio.h>#include<algorithm>#include<string.h>#include<iostream>#include<map>#include<set>#include<array>#definelllonglong#definef(i, s, e)for(int i = s; i <= e; i++)#defineff(i, s, e)for(int i = s; i >= e; i--)#definemaxn(ll)(2e5+5000)#defineINF0x3f3f3f3fusingnamespace std;int ans =0;int sx, sy, fx, fy;int n, m, t;int vis[100][100]={0};int dx[]={0,1,-1,0,0};// 上下左右int dy[]={0,0,0,-1,1};voiddfs(int x,int y){int xx, yy;// 如果当前坐标与目标坐标重合,则答案加1if(x == fx && y == fy){
ans++;return;}// 遍历当前坐标的四个方向f(i,1,4){// 计算当前坐标下一个坐标
xx = x + dx[i];
yy = y + dy[i];// 如果下一个坐标未访问过,且坐标合法(在网格内)if(!vis[xx][yy]&& xx >=1&& xx <= n && yy >=1&& yy <= m){// 标记当前坐标已访问过
vis[xx][yy]=1;// 递归访问当前坐标下一个坐标dfs(xx, yy);// 回溯,取消当前坐标的访问标记
vis[xx][yy]=0;}}}intmain(void){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> t;
cin >> sx >> sy >> fx >> fy;
vis[sx][sy]=1;int u, v;f(i,1, t){
cin >> u >> v;
vis[u][v]=1;}dfs(sx, sy);
cout << ans <<"\n";return0;}
B - 马的遍历
题目大意:
给出起始点,要求你计算出马到达棋盘上任意一个点最少要走几步
思路:
初始方向数组,然后用BFS搜索即可
Code
#include<stdio.h>#include<algorithm>#include<string.h>#include<iostream>#include<map>#include<set>#include<queue>#include<array>#definelllonglong#definef(i, s, e)for(int i = s; i <= e; i++)#defineff(i, s, e)for(int i = s; i >= e; i--)#definemaxn(ll)(2e5+5000)#defineINF0x3f3f3f3fusingnamespace std;// set<int>::iterator it;int n, m, x, y;
queue<array<int,2>> q;int cnt[550][550];int vis[550][550]={0};int dx[]={0,-1,-2,-2,-1,1,2,2,1};int dy[]={0,2,1,-1,-2,2,1,-1,-2};voidbfs(int x,int y){// 将起点放入队列
q.push({x, y});int xx, yy;// 当队列不为空时,取出队列中的元素,进行BFSwhile(!q.empty()){
xx = q.front()[0];
yy = q.front()[1];
q.pop();// 遍历8个方向f(i,1,8){int t1 = xx + dx[i];int t2 = yy + dy[i];// 如果该点没有被访问过,且在边界内,则将其加入队列,并记录步数if(!vis[t1][t2]&& t1 >=1&& t1 <= n && t2 >=1&& t2 <= m){
vis[t1][t2]=1;
q.push({t1, t2});
cnt[t1][t2]= cnt[xx][yy]+1;}}}}intmain(void){// ios::sync_with_stdio(false);// cin.tie(0);// cout.tie(0);
cin >> n >> m >> x >> y;memset(cnt,-1,sizeof(cnt));
cnt[x][y]=0;
vis[x][y]=1;bfs(x, y);f(i,1, n){f(j,1, m){printf("%-5d", cnt[i][j]);}printf("\n");}return0;}
#include<stdio.h>#include<algorithm>#include<string.h>#include<iostream>#include<map>#include<set>#include<array>#include<vector>#include<string>#definelllonglong#definef(i, s, e)for(int i = s; i <= e; i++)#defineff(i, s, e)for(int i = s; i >= e; i--)#definemaxn(ll)(2e5+5000)#defineINF0x3f3f3f3fusingnamespace std;// set<int>::iterator it;int n, k;int ans;char a[10][10];int vis[10]={0};voiddfs(int i,int cnt)// 行数与计数{if(cnt == k){
ans++;return;}if(i > n -1){return;}f(j,0, n -1){//考察是否能放if(!vis[j]&& a[i][j]=='#'){
vis[j]=1;dfs(i +1, cnt +1);// 这行放;
vis[j]=0;}}dfs(i +1, cnt);// 这行不放;}voidsolve(){
ans =0;memset(vis,0,sizeof(vis));f(i,0, n -1){
cin >> a[i];}dfs(0,0);
cout << ans <<'\n';}intmain(void){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);while(1){
cin >> n >> k;if(n ==-1&& k ==-1){break;}solve();}return0;}
E - 马走日
题目大意:
给定一个初始点,要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
思路:
一边搜,一边计数即可
Code
#include<stdio.h>#include<algorithm>#include<string.h>#include<iostream>#include<map>#include<set>#include<array>#include<vector>#include<string>#include<queue>#definelllonglong#definef(i, s, e)for(int i = s; i <= e; i++)#defineff(i, s, e)for(int i = s; i >= e; i--)#definemaxn(ll)(2e5+5000)#defineINF0x3f3f3f3fusingnamespace std;// set<int>::iterator it;int n, m, x, y;int ans =0;int vis[100][100];int dx[]={0,1,2,2,1,-1,-2,-2,-1};int dy[]={0,-2,-1,1,2,2,1,-1,-2};voiddfs(int x,int y,int k){if(k == n * m -1){
ans++;return;}int xx, yy;f(i,1,8){
xx = x + dx[i];
yy = y + dy[i];if(!vis[xx][yy]&& xx >=0&& xx < n && yy >=0&& yy < m){
vis[xx][yy]=1;dfs(xx, yy, k +1);
vis[xx][yy]=0;}}return;}voidsolve(){
cin >> n >> m >> x >> y;memset(vis,0,sizeof(vis));
ans =0;
vis[x][y]=1;//记得初始化dfs(x, y,0);
cout << ans <<'\n';return;}intmain(void){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int t;
cin >> t;while(t--){solve();}return0;}