dfs
ABC 236 D - Dance
题目链接
https://atcoder.jp/contests/abc236/tasks/abc236_d
解析
- 有点dfs与剪枝的意味??不清楚是不是叫剪枝
- 就是说通过设定一些枚举规则,使得对于本问题来说,没有枚举少一些情况
- 枚举规则可以参考官方题解
- 大概思路就是一层dfs枚举两个数,第一维是剩余数中最小的,第二维是剩余数中的随便一个,可以学习一下一对一对地搞dfs的代码思路。
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
const int N = 30;
vector<PII> vec;
int ans, n, res;
int g[N][N];
bool st[N];
void dfs(int u)
{
if(u == n + 1){
int ans = 0;
for(auto t : vec) {
ans ^= g[t.first][t.second];
//cout << t.first << ' ' << t.second << " ";
}
//puts("");
res = max(res, ans);
return;
}
int mmin;
for(int i = 1; i <= 2 * n; i ++){
if(!st[i]){
mmin = i;
break;
}
}
st[mmin] = true;
for(int i = 1; i <= 2 * n; i ++){
if(!st[i]){
vec.push_back({mmin, i}); st[i] = true;
dfs(u + 1);
vec.pop_back(); st[i] = false;
}
}
st[mmin] = false;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= 2 * n; i ++){
for(int j = i + 1; j <= 2 * n; j ++){
scanf("%d", &g[i][j]);
}
}
dfs(1);
printf("%d\n", res);
return 0;
}
842.排列数字
题目链接
https://www.acwing.com/problem/content/844/
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10;
int n;
bool st[N];
int f[N];
void dfs(int u)
{
if(u == n + 1){
for(int i = 1; i <= n; i ++) printf("%d ", f[i]);
puts("");
}
for(int i = 1; i <= n; i ++){
if(!st[i]){
st[i] = true;
f[u] = i;
dfs(u + 1);
st[i] = false;
}
}
}
int main()
{
scanf("%d", &n);
dfs(1);
return 0;
}
285. 没有上司的舞会
题目链接
https://www.acwing.com/problem/content/287/
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 6010;
int n;
int h[N], e[N], ne[N], idx;
int happy[N];
bool has_father[N];
int f[N][2];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u)
{
f[u][1] = happy[u];
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
dfs(j);
f[u][0] += max(f[j][0], f[j][1]);
f[u][1] += f[j][0];
}
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &happy[i]);
memset(h, -1, sizeof h);
for(int i = 1; i < n; i ++){
int a, b;
scanf("%d%d", &a, &b);
add(b, a);
has_father[a] = true;
}
int root = 1;
while(has_father[root]) root ++;
dfs(root);
printf("%d\n", max(f[root][0], f[root][1]));
return 0;
}
901.滑雪
题目链接
https://www.acwing.com/problem/content/903/
解析
记忆化搜索
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 310;
int h[N][N];
int f[N][N];
int m, n;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int dp(int x, int y)
{
if(f[x][y] != -1) return f[x][y];
f[x][y] = 1;
for(int i = 0; i < 4; i ++){
int a = x + dx[i], b = y + dy[i];
if(a >= 1 && a <= m && b >= 1 && b <= n && h[a][b] < h[x][y])
f[x][y] = max(f[x][y], dp(a, b) + 1);
}
return f[x][y];
}
int main()
{
scanf("%d%d", &m, &n);
for(int i = 1; i <= m; i ++)
for(int j = 1; j <= n; j ++)
scanf("%d", &h[i][j]);
int res = 0;
memset(f, -1, sizeof f);
for(int i = 1; i <= m; i ++)
for(int j = 1; j <= n; j ++)
res = max(res, dp(i, j));
printf("%d\n", res);
return 0;
}
843. n皇后问题
题目链接
https://www.acwing.com/problem/content/845/
解析
感觉老是把递归出口写少一层
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20;
int n;
char a[N][N];
bool row[N], col[N], dg[N], udg[N];
void dfs(int u)
{
if(u == n + 1){
for(int i = 1; i <= n; i ++) printf("%s\n", a[i] + 1);
puts("");
return;
}
for(int i = 1; i <= n; i ++){
if(!col[i] && !dg[u + i] && !udg[n - u + i]){
a[u][i] = 'Q';
col[i] = dg[u + i] = udg[n - u + i] = true;
dfs(u + 1);
col[i] = dg[u + i] = udg[n - u + i] = false;
a[u][i] = '.';
}
}
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
a[i][j] = '.';
dfs(1);
return 0;
}
1875. 贝茜的报复
题目链接
https://www.acwing.com/problem/content/1877/
解析
咱就是说吧dfs想简单了,写了个复杂度和7层循环不相上下的dfs,应该先对题目式子进行化简,转化成对于每个数奇偶的dfs,记录每个字母的奇偶取值的个数,然后算出最终答案。
但其实如果只是暴搜每个数的奇偶状态,可以转化为二进制暴力枚举。
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 10;
int n;
map<char, int> mp1;
map<char, int> mp2;
int ans[N];
int cnt;
string str = "BESIOMG";
void dfs(int u, int x)
{
if(u == 7){
if((ans[0] + ans[3]) % 2 && (ans[6] + ans[4] + ans[1] + ans[2]) % 2 && ans[5] % 2) return;
cnt += x;
return;
}
ans[u] = 1;
dfs(u + 1, x * mp1[str[u]]);
ans[u] = 2;
dfs(u + 1, x * mp2[str[u]]);
}
int main()
{
scanf("%d\n", &n);
while(n --)
{
char op;
int x;
scanf("%c %d\n", &op, &x);
if(x % 2) mp1[op] ++;
else mp2[op] ++;
}
dfs(0, 1);
printf("%d\n", cnt);
return 0;
}
1929. 镜子田地
题目链接
https://www.acwing.com/problem/content/1931/
解析
-
整体框架是暴力枚举所有的入射光线,计算每种情况下的反射数,取最大值。
-
计算反射数要进行搜索,此处用的dfs。(感觉bfs好像也行?)
-
搜索的困难在于判断到达某一格子后给出出射方向,本题通过异或的方式对方向的判断做了很好的简化。
-
dfs过程中要传的参数比较多,总而言之就是会用到的都要传。
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
char a[N][N];
int n, m;
int ans;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; //0、1、2、3
void dfs(int x, int y, int d, int u){
ans = max(ans, u);
int nx, ny, nd;
if(a[x][y] == '/') nd = d ^ 1;
else nd = d ^ 3;
nx = x + dx[nd], ny = y + dy[nd];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m)
dfs(nx, ny, nd, u + 1);
return;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%s", a[i] + 1);
//for(int i = 1; i <= n; i ++) cout << a[i] + 1 << endl;
//水平方向射入的光线
for(int i = 1; i <= n; i ++){
dfs(i, 1, 1, 1);
dfs(i, m, 3, 1);
}
//垂直方向射入的光线
for(int i = 1; i <= m; i ++){
dfs(1, i, 2, 1);
dfs(n, i, 0, 1);
}
printf("%d\n", ans);
return 0;
}
2005. 马蹄铁
题目链接
https://www.acwing.com/problem/content/2007/
解析
dfs。感觉想明白传什么参数很重要,庆祝我也可以写dfs嘻嘻(逛超市去喽
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10;
int n;
char a[N][N];
bool st[N][N];
int ans = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void dfs(int x, int y, int l, int r){
if(l == r && l > 0){
ans = max(ans, l + r);
return;
}
for(int i = 0; i < 4; i ++){
int nx = x + dx[i], ny = y + dy[i];
if(nx < 1 || nx > n || ny < 1 || ny > n) continue;
if(st[nx][ny]) continue;
if(r > 0 && a[nx][ny] == ')'){
st[nx][ny] = true;
dfs(nx, ny, l, r + 1);
st[nx][ny] = false;
}
if(r == 0){
st[nx][ny] = true;
if(a[nx][ny] == '(') dfs(nx, ny, l + 1, r);
st[nx][ny] = false;
st[nx][ny] = true;
if(a[nx][ny] == ')') dfs(nx, ny, l, r + 1);
st[nx][ny] = false;
}
}
return;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%s", a[i] + 1);
st[1][1] = true;
if(a[1][1] == '(') dfs(1, 1, 1, 0);
else dfs(1, 1, 0, 1);
printf("%d\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库