7-1 输出全排列
思路
基本的DFS题目 使用数组存储全排列数 设置一个check数组检查对应数字是否使用过即可
代码
#include<iostream>
using namespace std;
int n;
int arr[10];
bool arrcheck[10];
//cnt 记录当前答案数组中存储了多少个数字,当存够n个以后就可以开始输出
void DFS(int cnt)
{
if (cnt > n)
{
for (int i = 1; i <= n; i++)
{
printf("%d", arr[i]);
}
printf("\n");
return;
}
for (int i = 1; i <= n; i++)
{
if (arrcheck[i])continue;
arr[cnt] = i;
arrcheck[i] = 1;
DFS(cnt + 1);
arrcheck[i] = 0;
}
}
int main()
{
cin >> n;
DFS(1);
return 0;
}
7-2 山
思路
我使用的是BFS,呃。。。因为山的状态和BFS的动态图里呈现的很相似,是水波式的
代码
#include<iostream>
#include<queue>
using namespace std;
const int N = 2005;
int m, n;
//本题是以山为基础,查询一个山向左向右向前向后是否还是山
int map[N][N];
bool mapcheck[N][N];
//前后左右捏
int detx[4] = { 0,1,0,-1 };
int dety[4] = { 1,0,-1,0 };
struct pos{
int x, y;
};
int ans;
int main()
{
cin >> m >> n;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
cin >> map[i][j];
for(int i=1;i<=m;i++)
for (int j = 1; j <= n; j++)
{
if (map[i][j] == 0 || mapcheck[i][j])continue;
ans++;
queue<pos> que;
struct pos a;
a.x = i; a.y = j;
que.push(a);
while (!que.empty())
{
a.x = que.front().x;
a.y = que.front().y;
que.pop();
for (int k = 0; k < 4; k++)
{
struct pos to;
to.x = a.x + detx[k];
to.y = a.y + dety[k];
if (map[to.x][to.y] == 1 && !mapcheck[to.x][to.y])
{
mapcheck[to.x][to.y] = 1;
que.push(to);
}
}
}
}
printf("%d", ans);
return 0;
}
7-3 跳跃
思路
是比较简单的只有两个方向的DFS,同时同时!只要特别注意如果你经过一个点后,就不需要再走这个点了(在代码中。这个点往后的向左向右的情况已经全部涵盖了)在经过这点说明是重复了,会超时
代码
#include<iostream>
using namespace std;
const int N = 5 * 1e4;
int line[N];
bool linecheck[N];
int m, st;
bool ans;
void DFS(int index)
{
if (ans == 1)return;
if (line[index] == 0)
{
ans = 1;
return;
}
int l = index - line[index];
int r = index + line[index];
if (ans == 1)return;
if (l >= 0 && !linecheck[l])
{
linecheck[l] = 1;
DFS(l);
}
if (ans == 1)return;
if (r < m && !linecheck[r])
{
linecheck[r] = 1;
DFS(r);
}
if (ans == 1)return;
}
int main()
{
cin >> m;
for (int i = 0; i < m; i++)
cin >> line[i];
cin >> st;
linecheck[st] = 1;
DFS(st);
if (ans)printf("True");
else printf("False");
return 0;
}
7-4 最长光路
思路
这道题的难点有三点,一是处理镜子,二是判断环,三是合理存储数据。
由于初始方向是给定的,在不遇到镜子时不会改变(这点和地图式的DFS有很大差别),同时,存储数据时也是给初始的四个方向存储,在这里,使用类似EXCEL的绝对与相对引用的表达,我们需要一个绝对引用式的不改变的数字来表示初始的方向,以记录在U R D L四种方向的答案,同时,还需要一个相对引用式的可改变的数字作为真实的行走方向,于是出现了全局变量i和局部的target
至于判断环,则学习了一般的思路,如果一个点经过超过四次,则表明已经成环(对于一个点,不管如何走,在不成环的情况下应该至多有四次经过)此时,改变了一般的检查图,不需要检查这个点是否已经走过,只需要记录经过这个点的次数。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 500 + 5;
char Map[maxn][maxn];
int Mapcheck[505][505][4];
int sx, sy;
int n, m;
int ans[4] = { 1,1,1,1 };
//光上右下左
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };
bool flag;
int i = 0;
void DFS(int tox, int toy, int target)
{
Mapcheck[tox][toy][i]++;
//成环
if (Mapcheck[tox][toy][i] > 4)
{
flag = true;
return;
}
//越过边界 表明光线射出
if (tox<1 || tox>n || toy<1 || toy>m)
{
return;
}
//剩下的表明已经全部合法(不越界也没有成环)
if (Map[tox][toy] == '.')
{
ans[i]++;
DFS(tox + dx[target], toy + dy[target], target);
}
else if (Map[tox][toy] == 'C')
{
return;
}
else if (Map[tox][toy] == '/')
{
if (target == 0) target = 1;
else if (target == 1) target = 0;
else if (target == 2) target = 3;
else target = 2;
ans[i]++;
DFS(tox + dx[target], toy + dy[target], target);
}
else if (Map[tox][toy] == '\\')
{
if (target == 0) target = 3;
else if (target == 1) target = 2;
else if (target == 2) target = 1;
else target = 0;
ans[i]++;
DFS(tox + dx[target], toy + dy[target], target);
}
Mapcheck[tox][toy][i] = 0;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> Map[i][j];
}
}
cin >> sx >> sy;
for(int i=0;i<4;i++)
Mapcheck[sx][sy][i] = 1;
//int flag = false;
for (i = 0; i < 4; i++)
{
int target = i;
//记录是否走过
DFS(sx + dx[i], sy + dy[i], target);
if (flag)break;
}
if (flag)
{
if (i == 0)printf("U\nCOOL");
else if (i == 1)printf("R\nCOOL");
else if (i == 2)printf("D\nCOOL");
else if (i == 3)printf("L\nCOOL");
}
else
{
int max = -1, ed = -1;
for (i = 0; i < 4; i++)
{
if (max < ans[i])
{
max = ans[i];
ed = i;
}
}
i = ed;
if (i == 0)printf("U\n%d", ans[i]);
else if (i == 1)printf("R\n%d", ans[i]);
else if (i == 2)printf("D\n%d", ans[i]);
else if (i == 3)printf("L\n%d", ans[i]);
}
return 0;
}
7-5 回文数文回
思路
参考大犇们的代码和思路以后,挑选出这样的解题方式
通过取前五位数,并记录五位数的前四位数以还原原数字的办法(因为我们知道,1e9的数据是不会超过整型的)所以只需要还原数字,比较是否与给定数字小或相等即可
代码
#include<bits/stdc++.h>
using namespace std;
int n;
int ans;
int Ans(int n)
{
//只取前四位 temp保存最终答案
int temp = n;
int arr[4]={0},i=0;
n /= 10;//舍去第五位
do
{
//取数并倒置存储
arr[i++] = n % 10;
n /= 10;
} while (n != 0);
for ( i = 0; i < 4; i++)
{
temp *= 10;
temp += arr[i];
}
return temp;
}
int main()
{
cin >> n;
for (int i = 10000; i <= 99999; i++)
{
if (Ans(i) <= n)
{
ans++;
}
}
printf("%d", ans);
return 0;
}