如何用DFS算法训练识别模型?

摘要:dfs算法训练 洛谷题单 https:www.luogu.com.cntraining972732 开数组的范围 1. int 全局二维 256MB = 256 × 1024 ×
dfs算法训练 洛谷题单 https://www.luogu.com.cn/training/972732 开数组的范围 1. int 全局二维 256MB = 256 × 1024 × 1024 = ≈ 6700 万 int 3000×3000 int:36MB ✅ 4000×4000 int:64MB ✅ 5000×5000 int:100MB ✅ 8000×8000 int:256MB ❌ 刚好顶满 蓝桥全局 int 安全:≤ 5000×5000比赛里开到 3000×3000 完全稳 2. bool 全局二维 16000×16000 bool:256MB ❌ 顶满 10000×10000 bool:100MB ✅ 5000×5000 bool:25MB ✅ 全排列 输出 n 的全排列。 样例输入: 3 样例输出: 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 使用递归 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; //全排列 int n; /**样例输入: 3 样例输出: 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 **/ void dfs(int x){ if(x==n+1){ for(int i=1;i<=n;i++){ cout<<a[i]<<" "; } cout<<endl; return; } for(int i=1;i<=n;i++){ if(b[i]==0){ b[i]=1; a[x]=i; dfs(x+1); a[x]=0; b[i]=0; } } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; dfs(1); return 0; } 使用next_permutation 方法一 主要还是去求这个,排列组合 #include <bits/stdc++.h> using namespace std; int n,m; int a[100]; int main() { scanf("%d",&n); int tot=1; for(int i=1;i<=n;++i) { a[i]=i; tot*=i; } for(int i=1;i<=tot;++i) { for(int j=1;j<=n;++j) printf(" %d",a[j]); //输出格式注意 next_permutation(a+1,a+n+1); printf("\n"); } return 0; } 方法二 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; //全排列 int n; /**样例输入: 3 样例输出: 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 **/ signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; for(int i=1;i<=n;i++){ a[i]=i; } do{ for(int i=1;i<=n;i++){ cout<<a[i]<<" "; } cout<<endl; }while(next_permutation(a+1,a+n+1)); return 0; } 选或者不选 #include<bits/stdc++.h> using namespace std; int n; // 物品个数 int a[25]; // 物品价值/重量等属性 bool vis[25]; // 标记选了哪些(可选) // ========== 核心DFS模板 ========== // k: 当前考虑第k个物品 // 其他参数:根据题目需要,如当前和、当前重量、当前价值等 void dfs(int k, int current_sum) { if(k > n) { // 所有物品处理完毕 // 在这里处理最终答案 // 比如:更新最大/最小值,统计方案数,输出方案等 ans = max(ans, current_sum); return; } // 选择1:不选第k个物品 vis[k] = false; // 标记未选(可选) dfs(k + 1, current_sum); // 状态不变,继续下一个 // 选择2:选第k个物品 vis[k] = true; // 标记已选(可选) dfs(k + 1, current_sum + a[k]); // 状态更新,继续下一个 // vis[k] = false; // 如果vis是全局数组,需要回溯 } int main() { cin >> n; for(int i = 1; i <= n; i++) cin >> a[i]; dfs(1, 0); // 从第1个开始,初始状态 return 0; } 常见变形 1. 求子集和等于target的方案数 void dfs(int k, int sum) { if(k > n) { if(sum == target) ans++; return; } dfs(k + 1, sum); // 不选 dfs(k + 1, sum + a[k]); // 选 } 2. 求选k个数的最大/最小和 cpp 复制 void dfs(int pos, int cnt, int sum) { // cnt: 已选个数 if(cnt > k) return; // 剪枝:选多了 if(pos > n) { if(cnt == k) ans = max(ans, sum); return; } dfs(pos + 1, cnt + 1, sum + a[pos]); // 选 dfs(pos + 1, cnt, sum); // 不选 } 3. 记录具体方案(回溯) cpp 复制 vector<int> path; void dfs(int k, int sum) { if(k > n) { if(sum == target) { for(int x : path) cout << x << " "; cout << endl; } return; } // 不选 dfs(k + 1, sum); // 选 path.push_back(a[k]); dfs(k + 1, sum + a[k]); path.pop_back(); // 回溯 } 4. 有重量限制(背包类) cpp 复制 void dfs(int k, int weight, int value) { if(weight > W) return; // 剪枝:超重 if(k > n) { ans = max(ans, value); return; } dfs(k + 1, weight, value); // 不选 dfs(k + 1, weight + w[k], value + v[k]); // 选 } BFS模板 — 最短路径(迷宫问题) #include <bits/stdc++.h> using namespace std; const int N = 110; int n, m; // 地图大小 char g[N][N]; // 地图:'.'表示空地,'#'表示障碍 int dist[N][N]; // 距离数组,-1表示未访问 int dx[4] = {-1, 0, 1, 0}; // 四个方向:上右下左 int dy[4] = {0, 1, 0, -1}; int bfs(int sx, int sy, int ex, int ey) { memset(dist, -1, sizeof dist); // 初始化距离为-1(未访问) queue<pair<int, int>> q; dist[sx][sy] = 0; // 起点距离为0 q.push({sx, sy}); // 起点入队 while (q.size()) { // 队列不为空 auto t = q.front(); // 取队首 q.pop(); int x = t.first, y = t.second; if (x == ex && y == ey) // 到达终点 return dist[x][y]; for (int i = 0; i < 4; i++) { // 遍历四个方向 int a = x + dx[i], b = y + dy[i]; // 边界检查 + 障碍检查 + 访问检查 if (a < 0 || a >= n || b < 0 || b >= m) continue; if (g[a][b] == '#') continue; // 障碍物 if (dist[a][b] != -1) continue; // 已访问过 dist[a][b] = dist[x][y] + 1; // 距离+1 q.push({a, b}); // 新点入队 } } return -1; // 无法到达 } int main() { cin >> n >> m; for (int i = 0; i < n; i++) cin >> g[i]; int res = bfs(0, 0, n-1, m-1); // 从左上到右下 cout << res << endl; return 0; } DFS模板 — 全排列/组合搜索 #include <bits/stdc++.h> using namespace std; const int N = 10; int n; int path[N]; // 当前路径/方案 bool used[N]; // 标记数字是否被使用 // 全排列:从n个数中选n个,有顺序 void dfs_permutation(int u) { // u表示当前填到第几个位置 if (u == n) { // 填满了,输出方案 for (int i = 0; i < n; i++) cout << path[i] << ' '; cout << endl; return; } for (int i = 1; i <= n; i++) { // 尝试每个数字 if (!used[i]) { // 如果i还没用过 used[i] = true; // 标记为使用 path[u] = i; // 填入当前位置 dfs_permutation(u + 1); // 递归填下一个位置 used[i] = false; // 回溯!恢复状态 } } } // 组合:从n个数中选k个,无顺序(选法,不考虑排列) void dfs_combination(int start, int k, int u) { // u:当前选了几个, start:从哪个数开始选(避免重复) if (u == k) { for (int i = 0; i < k; i++) cout << path[i] << ' '; cout << endl; return; } for (int i = start; i <= n; i++) { // 从start开始,避免选重复的 path[u] = i; dfs_combination(i + 1, k, u + 1); // 下一个从i+1开始选 // 这里不需要used数组,因为通过start控制不重复 } } // DFS求连通块( Flood Fill ) int dx[4] = {-1, 0, 1, 0}; int dy[4] = {0, 1, 0, -1}; char g[N][N]; bool vis[N][N]; void dfs_floodfill(int x, int y) { vis[x][y] = true; // 标记访问 for (int i = 0; i < 4; i++) { int a = x + dx[i], b = y + dy[i]; if (a < 0 || a >= n || b < 0 || b >= m) continue; if (g[a][b] == '#') continue; // 不是目标区域 if (vis[a][b]) continue; // 访问过 dfs_floodfill(a, b); // 递归搜索连通块 } } int main() { cout << "=== 全排列 ===" << endl; n = 3; dfs_permutation(0); cout << "\n=== 组合 C(4,2) ===" << endl; n = 4; dfs_combination(1, 2, 0); return 0; } 记忆化搜索模板(DFS + DP) #include <bits/stdc++.h> using namespace std; const int N = 510; int n, m; int g[N][N], f[N][N]; // f[i][j] 表示从(i,j)出发的最大值 int dfs(int x, int y) { if (f[x][y] != -1) return f[x][y]; // 记忆化:算过直接返回 f[x][y] = 1; // 至少包含自己 // 四个方向搜索 int dx[4] = {-1, 0, 1, 0}; int dy[4] = {0, 1, 0, -1}; for (int i = 0; i < 4; i++) { int a = x + dx[i], b = y + dy[i]; if (a >= 0 && a < n && b >= 0 && b < m && g[a][b] < g[x][y]) { f[x][y] = max(f[x][y], dfs(a, b) + 1); // 能滑下去就+1 } } return f[x][y]; } int main() { cin >> n >> m; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) cin >> g[i][j]; memset(f, -1, sizeof f); // 初始化为-1表示未计算 int res = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) res = max(res, dfs(i, j)); cout << res << endl; return 0; } B3621 枚举元组 B3621 枚举元组 - 洛谷 思路 我们可以去使用dfs去枚举每一个位置,用a[pos]=i,去记录当前位的值 void dfs(int pos){ if(pos==n+1){ for(int i=1;i<=n;i++){ cout<<a[i]<<" "; } cout<<endl; return; } for(int i=1;i<=k;i++){ a[pos]=i; dfs(pos+1); } } 表示一个萝卜一个坑位的意思 a【pos】=i,表示地pos个位置是i 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; int n; int k; void dfs(int pos){ if(pos==n+1){ for(int i=1;i<=n;i++){ cout<<a[i]<<" "; } cout<<endl; return; } for(int i=1;i<=k;i++){ a[pos]=i; dfs(pos+1); } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>k; dfs(1); return 0; } B3622 枚举子集 B3622 枚举子集(递归实现指数型枚举) - 洛谷 思路 因为我们发现每个位置都有两种状态,我们就可以去定义两种状态的,一个0,一个1,每次都有两个可能 所以我们只需要定义两个位置的状态 void dfs(int pos,int biao){ if(biao==0){ s+='N'; } if(biao==1){ s+='Y'; } if(pos==n){ cout<<s<<endl; s=s.substr(0,s.size()-1);//切除一下,相当于回塑 return; } dfs(pos+1,0); dfs(pos+1,1); s=s.substr(0,s.size()-1);//回溯 } 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; string s; int n; //用数字来表示状态 void dfs(int pos,int biao){ if(biao==0){ s+='N'; } if(biao==1){ s+='Y'; } if(pos==n){ cout<<s<<endl; s=s.substr(0,s.size()-1);//切除一下,相当于回塑 return; } dfs(pos+1,0); dfs(pos+1,1); s=s.substr(0,s.size()-1); } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; dfs(1,0); dfs(1,1); return 0; } B3623 枚举排列 B3623 枚举排列(递归实现排列型枚举) - 洛谷 思路 选择两个数组一个数组记录第几个位置选的是什么,第二个就是有没有被选过,被选过的我们不要,没被选择的我们才要,记得回塑 void dfs(int pos){ if(pos==k+1){ for(int i=1;i<=k;i++){ cout<<a[i]<<" "; } cout<<endl; return; } for(int i=1;i<=n;i++){ if(b[i]==0){ b[i]=1; }else{ continue; } a[pos]=i; dfs(pos+1); b[i]=0; } } 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; int n,k; void dfs(int pos){ if(pos==k+1){ for(int i=1;i<=k;i++){ cout<<a[i]<<" "; } cout<<endl; return; } for(int i=1;i<=n;i++){ if(b[i]==0){ b[i]=1; }else{ continue; } a[pos]=i; dfs(pos+1); b[i]=0; } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>k; dfs(1); return 0; } P10448 组合型枚举 P10448 组合型枚举 - 洛谷 思路 我们可以去设置,两个数值记录,有没有选过和到底有没有用过,然后我们枚举只要从上一个数中枚举就行了 for(int i=a[pos-1]+1;i<=n;i++){//关键代码 if(b[i]==0){ b[i]=1; }else{ continue; } a[pos]=i; dfs(pos+1); b[i]=0; } 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; int n,m; void dfs(int pos){ if(pos==m+1){ for(int i=1;i<=m;i++){ cout<<a[i]<<" "; } cout<<endl; return; } for(int i=a[pos-1]+1;i<=n;i++){ if(b[i]==0){ b[i]=1; }else{ continue; } a[pos]=i; dfs(pos+1); b[i]=0; } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>m; dfs(1); return 0; } P2089 烤鸡 P2089 烤鸡 - 洛谷 思路 相当于每个位置只能放1,2,3,枚举的去,我们可以去计算当前的总数和,然后去枚举好就行了 但是会超时有的 void dfs(int pos,int sum1){ if(sum1>n)return; if(pos==11&&sum1==n){ string s; for(int i=1;i<=10;i++){ s+=to_string(a[i])+" "; } ans.push_back(s); return; } for(int v=1;v<=3;v++){ a[pos]=v; dfs(pos+1,sum1+v); } } 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; int n; vector<string>ans; void dfs(int pos,int sum1){ if(sum1>n)return; if(pos==11&&sum1==n){ string s; for(int i=1;i<=10;i++){ s+=to_string(a[i])+" "; } ans.push_back(s); return; } for(int v=1;v<=3;v++){ a[pos]=v; dfs(pos+1,sum1+v); } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; dfs(1,0); if(ans.size()==0){ cout<<0<<endl; }else{ cout<<ans.size()<<endl; for(auto&s : ans){ cout<<s<<endl; } } return 0; } 减枝 可以进行减枝 if (n < 10 || n > 30) { cout << "0\n"; return 0; } 加一个这个代码 P15435[蓝桥杯 2025 国 Python B] 免费披萨 [P15435 蓝桥杯 2025 国 Python B] 免费披萨 - 洛谷 (luogu.com.cn) 思路 我们可以去枚举每个位置的数值然后,去进行dfs,尝试枚举每个可能,然后填充后再进行判断计算出gcd的 代码 #include<bits/stdc++.h> using namespace std; long long n,max_gcd=-1,minn=INT_MAX; int a[10],tot; void dfs(int pos) { if(pos==8) { string s=""; for(int i=1;i<=8;i++) s+=char(a[i]+'0'); for(int ins=0;ins<=8;ins++) for(int num=1;num<=8;num++) { string nine=s.substr(0,ins)+char(num+'0')+s.substr(ins); long long val=stoll(nine); long long now_gcd=__gcd(val,n); if(now_gcd>max_gcd) { max_gcd=now_gcd; minn=val; } else if(now_gcd==max_gcd) if(val<minn) minn=val; } return; } for(int i=1;i<=8;i++) { bool flag=0; for(int j=1;j<=pos;j++) if(a[j]==i) { flag=1; break; } if(!flag) { a[pos+1]=i; dfs(pos+1); } } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string s; cin>>s; n=stoll(s); dfs(0);/ cout<<minn; return 0; } P6183 [USACO10MAR] The Rock Game S [P6183 USACO10MAR] The Rock Game S - 洛谷 (luogu.com.cn) 思路:找到与当前只差一个的方案,判断是否走过,记录并输出。 Q:如何判断是否走过呢。 A:考虑转化,加入将O记为0,X记为1,这样每个状态都可以转化为一个二进制数,将他转换为十进制存储,判断也按十进制判断即可。 我们通过判断 考虑转化,加入将O记为0,X记为1,这样每个状态都可以转化为一个二进制数,将他转换为十进制存储,判断也按十进制判断即可。 void output(){//输出 for(int i=1;i<=1<<n;i++){ for(int j=1;j<=n;j++){ cout<<(ans[i][j]?'X':'O'); } cout<<endl; } } int cacl(){//转换二进制 int ans=0; for(int i=1;i<=n;i++){ ans=ans*2+a[i]; } return ans; } 然后dfs去扫描 到底有没有 void dfs(int pos){ if(pos==(1<<n)){ output();//找到一组 exit(0); } for(int i=1;i<=n;i++){ a[i]=!a[i]; if(vis[cacl()]){ a[i]=!a[i]; continue; } vis[cacl()]=true; for(int j=1;j<=n;j++){ ans[pos][j]=a[j];//存储答案 } dfs(pos+1);//继续搜索下一个 vis[cacl()]=false;//回溯 a[i]=!a[i];//注意:不能颠倒,被坑了一次 } } 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int b[N],c[N],pre[N]; int a[20]; int n; int vis[1<<20];//记录有没有走过的 int ans[1<<20][20],tot=0; void output(){ for(int i=1;i<=1<<n;i++){ for(int j=1;j<=n;j++){ cout<<(ans[i][j]?'X':'O'); } cout<<endl; } } int cacl(){ int ans=0; for(int i=1;i<=n;i++){ ans=ans*2+a[i]; } return ans; } void dfs(int pos){ if(pos==(1<<n)){ output();//找到一组 exit(0); } for(int i=1;i<=n;i++){ a[i]=!a[i]; if(vis[cacl()]){ a[i]=!a[i]; continue; } vis[cacl()]=true; for(int j=1;j<=n;j++){ ans[pos][j]=a[j];//存储答案 } dfs(pos+1);//继续搜索下一个 vis[cacl()]=false;//回溯 a[i]=!a[i];//注意:不能颠倒,被坑了一次 } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; for(int i=1;i<=n;i++){ cout<<"O"; } cout<<endl; vis[0]=true;//0直接是用过的 dfs(1);//从1开始搜索 return 0; } P13886 [蓝桥杯 2023 省 Python A] 分糖果 [P13886 蓝桥杯 2023 省 Python A] 分糖果 - 洛谷 (luogu.com.cn) 思路 我们可以这样想,每个位置可以分糖果的种类可以有两种,要么第一种要么第二种 ,我们就判断当前位置可以分的第一个的数量和第二个数量进行枚举。 枚举位置的情况,然后 #include <stdio.h> // 全局变量记录答案 long long ans = 0; // 参数说明: // idx: 当前处理第几个小朋友(0~6) // a: 已经分出去的第一种糖果数量 // b: 已经分出去的第二种糖果数量 void dfs(int index,int a,int b){ if(index==7){ if(a==9&&b==16){ ans++; } return; } for(int i=0;i<=9-a;i++){ for(int j=0;j<=16-b;j++){ int tatal=i+j; if(tatal>=2&&tatal<=5){ dfs(index+1,a+i,b+j); } } } } 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int ans=0; void dfs(int index,int a,int b){ if(index==7){ if(a==9&&b==16){ ans++; } return; } for(int i=0;i<=9-a;i++){ for(int j=0;j<=16-b;j++){ int tatal=i+j; if(tatal>=2&&tatal<=5){ dfs(index+1,a+i,b+j); } } } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); ans=0; dfs(0,0,0); cout<<ans<<endl; return 0; } P2404 自然数的拆分问题 P2404 自然数的拆分问题 - 洛谷 (luogu.com.cn) 思路 题目说是数字要从大到小,我们就就可以去枚举单前的数的范围 stat-s 直接拿这两个数去做参数,第一个表示下一个数的起始值,s表示 还剩下需要凑的数 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; int n; int len=0; //第一个表示下一个数的起始值,s表示 还剩下需要凑的数 void dfs(int stat,int s){ if(s==0){ if(len==1){ return; } for(int i=0;i<len;i++){ if(i>0)cout<<"+"; cout<<a[i]; } cout<<endl; return; } for(int i=stat;i<=s;i++){ a[len++]=i; dfs(i,s-i);//回塑 len--; } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; dfs(1,n); return 0; } P2386 放苹果 P2386 放苹果 - 洛谷 思路 这个题目主要还是不能选重复的然后就可以去想到记忆搜索法 - m == 0 或 n == 1:只有1种分法(全空/全放一个盘子) - m < 0 或 n == 0:0种分法(非法) 状态转移: - 情况1:至少有1个盘子空着 → 等价于 `dfs(m, n-1)`(少一个盘子,分法不变) - 情况2:所有盘子都有苹果 → 每个盘子先放1个,剩下 `m-n` 个苹果再分 → `dfs(m-n, n)` - 总方案数 = 情况1 + 情况2 公式:dfs(m, n) = dfs(m, n-1) + dfs(m-n, n) 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; int me[205][205]; int n; int m,t; //m个苹果分给n个选手; int dfs(int m,int n){ if(m==0||n==1)return 1; if(m<0 ||n==0)return 0; if(me[m][n]!=-1) return me[m][n]; return me[m][n]=dfs(m,n-1)+dfs(m-n,n); } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>t; for(int i=0;i<t;i++){ memset(me,-1,sizeof(me)); cin>>m>>n; cout<<dfs(m,n)<<endl; } return 0; } dp代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印 #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; int me[205][205]; int n; int m,t; signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int dp[205][205]; for(int i=0;i<=200;i++){ dp[i][1]=1;//i个苹果分给1个盘子 dp[0][i]=1;//0个苹果分给i个盘子 } for(int i=1;i<=200;i++){ for(int j=2;j<=200;j++){ if(i>=j){ dp[i][j]=dp[i][j-1]+dp[i-j][j]; }else{ dp[i][j]=dp[i][j-1]; } } } cin>>t; while(t--){ cin>>m>>n; cout<<dp[m][n]<<endl; } return 0; } P6566 [NOI Online #3 入门组] 观星 [P6566 NOI Online #3 入门组] 观星 - 洛谷 5 7 *...... ..**..* .*...*. ...*... ....*.. 3 4 思路 就是dfs和bfs 代码 dfs #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; bool vis[200][200]; // 修复 1:改小! int m,n; vector<string>s(n); int dx[8]={-1,-1,0,1,1,1,0,-1}; int dy[8]={0,1,1,1,0,-1,-1,-1}; int cnt=0; map<int, int> galaxy; void dfs(int x,int y){ // 修复 2:|| 全部正确 if(x<0 || x>=n || y<0 || y>=m)return; if (s[x][y] == '.' || vis[x][y]) return; vis[x][y]=true; cnt++; for(int i=0;i<8;i++){ int nx=x+dx[i]; int ny=y+dy[i]; dfs(nx,ny); } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>m; //s.resize(n); for(int i=0;i<n;i++){ cin>>s[i]; } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(s[i][j]=='*'&&!vis[i][j]){ cnt=0; dfs(i,j); galaxy[cnt]++; } } } int galaxy_cnt=galaxy.size(); int max_size=0; for(auto &p:galaxy){ max_size=max(max_size,p.first * p.second); } cout<<galaxy_cnt<<" "<<max_size<<endl; return 0; } bfs #include<bits/stdc++.h> using namespace std; const int MAX = 1505; // 支持 1500x1500 int n, m; vector<string> s; bool vis[MAX][MAX]; int dx[8] = {-1,-1,0,1,1,1,0,-1}; int dy[8] = {0,1,1,1,0,-1,-1,-1}; int bfs(int x, int y) { queue<pair<int,int>> q; q.push({x,y}); vis[x][y] = 1; int cnt = 1; while (!q.empty()) { auto [xx, yy] = q.front(); q.pop(); for (int i = 0; i < 8; i++) { int nx = xx + dx[i]; int ny = yy + dy[i]; if (nx >=0 && nx <n && ny >=0 && ny <m && !vis[nx][ny] && s[nx][ny] == '*') { vis[nx][ny] = 1; cnt++; q.push({nx, ny}); } } } return cnt; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m; s.resize(n); for (int i = 0; i < n; i++) { cin >> s[i]; } map<int, int> mp; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (s[i][j] == '*' && !vis[i][j]) { int sz = bfs(i, j); mp[sz]++; } } } int tot = mp.size(); long long max_gal = 0; for (auto &p : mp) { max_gal = max(max_gal, 1LL * p.first * p.second); } cout << tot << " " << max_gal << endl; return 0; } P1088 [NOIP 2004 普及组] 火星人 [P1088 NOIP 2004 普及组] 火星人 - 洛谷 思路 就是去把所有的枚举一遍 用next_permutaiton跑枚举 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],c[N],pre[N]; //全排列 int n; signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int m; cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++){ b[i]=i; } bool xx=false; int count=0; do{ if(xx==false){ for(int i=1;i<=n;i++){ if(a[i]!=b[i]){ break; } } xx=true; } count++; if(count==m+1){ for(int i=1;i<=n;i++){ cout<<a[i]<<" "; } break; } }while(next_permutation(a+1,a+n+1)); return 0; } B4482 [语言月赛 202601] 数字游戏 II 搜索加判断 [B4482 语言月赛 202601] 数字游戏 II - 洛谷 思路 就是搜索加回塑 我们先找到要填的来,然后去依次填写这个数,找到合适的,并且如果不行就要回到上一个去再找。 主要判断行和列和2x2怎么去判断一下。 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],pre[N]; //全排列 int n; vector<vector<int>>g(4,vector<int>(4,0)); bool check(int r, int c,int num){ for(int j=0;j<4;j++){//检查列 if(g[r][j]==num)return false; } for(int i=0;i<4;i++){ if(g[i][c]==num)return false; } int br=(r/2)*2; int bc=(c/2)*2; for(int i=br;i<br+2;i++){ for(int j=bc;j<bc+2;j++){ if(g[i][j]==num)return false; } } return true; } bool nextfind(int &r,int &c){ for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ if(g[i][j]==0){ r=i,c=j; return true; } } } return false; } bool solve(){ int r,c; //如果没有空位置,代表解完了。 if(!nextfind(r,c))return true; //尝试1-4; for(int num=1;num<=4;num++){ if(check(r,c,num)){ g[r][c]=num; if (solve()) return true;//递归求解 g[r][c]=0;//回塑 } } return false;//无解 } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ cin>>g[i][j]; } } solve(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { cout << g[i][j] << (j < 3 ? ' ' : '\n'); } } return 0; } B3862 图的遍历(简单版) B3862 图的遍历(简单版) - 洛谷 思路 思路有两种,一种是从最大的开始找本身开始找哪些可以到达这个的最大值,叫 反向图 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],pre[N]; //全排列 int n,m; vector<int>g[N]; int ans[N]; bool vis[N]; void dfs(int u,int val){ vis[u]=true; ans[u]=val; for(int v:g[u]){ if(!vis[v]){ dfs(v,val); } } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>m; for(int i=0;i<m;i++){ int u,v; cin>>u>>v; g[v].push_back(u); } for(int i=n;i>=1;i--){ if(!vis[i]){ dfs(i,i); } } for(int i=1;i<=n;i++){ cout<<ans[i]<<" "; } return 0; } 最基础的暴力去搜索那个是最大的 搜索图 void dfs(int u){ vis[u]=true; max1=max(max1,u); for(int v:g[u]){ if(!vis[v]){ dfs(v); } } } #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],pre[N]; //全排列 int n,m; vector<int>g[N]; int ans[N]; bool vis[N]; int max1; void dfs(int u){ vis[u]=true; max1=max(max1,u); for(int v:g[u]){ if(!vis[v]){ dfs(v); } } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>m; for(int i=0;i<m;i++){ int u,v; cin>>u>>v; g[u].push_back(v); } for(int i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); max1=i; dfs(i); cout<<max1<<(i<n?' ':'\n'); } return 0; } P1149 [NOIP 2008 提高组] 火柴棒等式 思路 暴力 把1-2000的数的都存在数组中 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],pre[N]; //全排列 int n,m; vector<int>g[N]; int ans=0; const int num[] = {6,2,5,5,4,5,6,3,7,6}; signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; a[0] = 6; //数字 0 有 6 个火柴 for (int i = 1;i <= 2000;i++){ for (int j = i;j;j /= 10){ //从最高位开始,一个数位一个数位地加上火柴数 a[i] += num[j % 10]; } } for (int i = 0;i <= 1000;i++){ for (int j = 0;j <= 1000;j++){ if (a[i] + a[j] + a[i + j] + 4 == n){ //a[i] 就是第一个数,a[j] 就是第二个数。 ans++; //a[i + j]就是第三个数。加上的 4 就是 + 和 =。 } } } cout << ans << endl; return 0; } P8801 [蓝桥杯 2022 国 B] 最大数字 题解 [P8801 蓝桥杯 2022 国 B] 最大数字 - 洛谷 思路 分情况去讨论,可以分两种都可以让数字变成9,分一种,分第二种,最后如果都不能那就优先把加的全部用上。 如果要用非常暴力的方法去解决的话也是可以的 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; //int a[N],b[N],pre[N]; int n,a,b; string s,ans; void dfs(int k,int c,int d,string str){ if(k==n){ if(str>ans){ ans=str; } return; } for(int i=c;i<=a;i++){ for(int j=d;j<=b;j++){ int num = str[k] - '0'; num = (num + i) % 10; // 先加i次 num = (num - j + 10) % 10; // 再减j次 str[k]=num+'0'; dfs(k+1,i,j,str); } } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>s; cin>>a>>b; n=s.size(); dfs(0,0,0,s); cout<<ans<<endl; return 0; } 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; //int a[N],b[N],pre[N]; int n,a,b; string s,ans; void dfs(int k,int c,int d,string str){ if(k==n){ if(str>ans){ ans=str; } return; } int x=9-str[k]+'0'; int y=str[k]-'0'+1; int old=str[k]; if(c+x<=a&&d+y<=b){//如果两种都能变九,都尝试一下 str[k]='9'; dfs(k+1,c+x,d,str); dfs(k+1,c,d+y,str); }else if(c+x<=a){//只有一可以 str[k]='9'; dfs(k+1,c+x,d,str); }else if(d+y<=b){//只有二可以 str[k]='9'; dfs(k+1,c,d+y,str); }else{ str[k]+=a-c; dfs(k+1,a,d,str); } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>s; cin>>a>>b; n=s.size(); dfs(0,0,0,s); cout<<ans<<endl; return 0; } P12266 [蓝桥杯 2024 国 Python B] 不同的总分值 思路 是选这个和不选这个可以达到的和 代码 #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; //int a[N],b[N],pre[N]; int n; int num[20]={0,5,5,10,10,15,15,20,20,25,25}; bool b[210]; int ans=0; void dfs(int k,int s){ if(k>10){ b[s]=1; for(int i=1;i<=10;i++){ cout<<b[i]<<" "; } memset(b,0,sizeof(b)); cout<<endl; return; } dfs(k+1,s),dfs(k+1,s+num[k]); } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); dfs(1,0); // for(int i=0;i<=150;i++){ // ans+=b[i]; // } cout<<ans<<endl; return 0; } P10578 [蓝桥杯 2024 国 A] 旋转九宫格 [P10578 蓝桥杯 2024 国 A] 旋转九宫格 - 洛谷 思路 这个我们可以逆着推,为什么是bfs呢,就是我们根据当前的状态去向外扩展,所有的状态,这个时候我们就可以去把这个数的状态去全部得到 直接看代码 代码 bfs #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],pre[N]; int t; string str="123456789"; map<string,int>h; queue<string>q; void bfs(){ q.push(str); h[str]=1; while(q.size()){ string s=q.front(); q.pop(); string v[4]={s,s,s,s};//这里的 s 代表的不是字符 s,而是 s 字符串。 //左上角区域逆时针旋转 v[0][0]=s[1],v[0][4]=s[3]; v[0][1]=s[4],v[0][3]=s[0]; //右上角区域逆时针旋转 v[1][1]=s[2],v[1][5]=s[4]; v[1][2]=s[5],v[1][4]=s[1]; v[2][3]=s[4];v[2][6]=s[3];//左下角区域逆时针旋转 v[2][4]=s[7];v[2][7]=s[6]; v[3][4]=s[5];v[3][7]=s[4];//右下角区域逆时针旋转 v[3][5]=s[8];v[3][8]=s[7]; //主要因为这里是逆向的,所以就是这样子要寻找逆向的旋转 for(int i=0;i<4;i++){ if(!h[v[i]]){ h[v[i]]=h[s]+1; if (v[i]==str) break; q.push(v[i]); } } } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>t; bfs(); while(t--){ string s; for(int i=0;i<9;i++){ char c; cin>>c; s+=c; } cout<<h[s]-1<<endl; } return 0; } P10386 [蓝桥杯 2024 省 A] 五子棋对弈 [P10386 蓝桥杯 2024 省 A] 五子棋对弈 - 洛谷 思路 博弈我们可以将他看出一维的数组,然后因为棋盘都是5x5要赢的话只有12种情况,我们可以把这些全部的排列全部写出来,然后去判断到底那些是要的 代码 bfs #include<bits/stdc++.h> #define int long long #define lll __uint128_t #define PII pair<int ,int> #define endl '\n' using namespace std; #define yn(ans) printf("%s\n", (ans)?"Yes":"No"); #define YN(ans) printf("%s\n", (ans)?"YES":"NO"); #define REP(i, e) for (int i = 0; i < (e); ++i) #define REP1(i, s, e) for (int i = (s); i <=(e); ++i) #define TESTS int t; cin >> t; while (t--) #define TEST const int N=2e5+10,M=1e3+10,mod=1e9+7; int a[N],b[N],pre[N]; int ans=0; int r=0,t=0; void pd(){ if(!((a[1]+a[2]+a[3]+a[4]+a[5])%5))return; if(!((a[6]+a[7]+a[8]+a[9]+a[10])%5))return; if(!((a[11]+a[12]+a[13]+a[14]+a[15])%5))return; if(!((a[16]+a[17]+a[18]+a[19]+a[20])%5))return; if(!((a[21]+a[22]+a[23]+a[24]+a[25])%5))return; if(!((a[1]+a[6]+a[11]+a[16]+a[21])%5))return; if(!((a[2]+a[7]+a[12]+a[17]+a[22])%5))return; if(!((a[3]+a[8]+a[13]+a[18]+a[23])%5))return; if(!((a[4]+a[9]+a[14]+a[19]+a[24])%5))return; if(!((a[5]+a[10]+a[15]+a[20]+a[25])%5))return; if(!((a[1]+a[7]+a[13]+a[19]+a[25])%5))return; if(!((a[5]+a[9]+a[13]+a[17]+a[21])%5))return; ans++; } void dfs(int k){ if(k==26){ pd(); } if(r<=12){ a[k]=1; r++; dfs(k+1); r--; } if(t<=11){ a[k]=0; t++; dfs(k+1); t--; } } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); dfs(1); cout<<ans<<endl; return 0; } P13877 [蓝桥杯 2023 省 Java A] 与或异或 [P13877 蓝桥杯 2023 省 Java A] 与或异或 - 洛谷 暴力枚举 主要这个门一共有10个选择我们可以直接去枚举这个10种状态。 代码 #include <iostream> using namespace std; int dd[] = {1, 2, 3}; int calc(int a, int b, int op){ if (op == 1) return a & b; if (op == 2) return a | b; if (op == 3) return a ^ b; } int main() { int ans = 0; for (int a : dd) for (int b : dd) for (int c : dd) for (int d : dd) for (int e : dd) for (int f : dd) for (int g : dd) for (int h : dd) for (int i : dd) for (int j : dd) { int k = calc(1, 0, a), l = calc(0, 1, b), m = calc(1, 0, c), n = calc(0, 1,d); int o = calc(k, l, e), p = calc(l, m, f), q = calc(m, n, g); int r = calc(o, p, h), s = calc(p, q, i); int t = calc(r, s, j); if (t == 1) ans++; } cout << ans << endl; return 0; } dfs #include <iostream> using namespace std; int ans; // 记录满足条件的方案数 int arr[5][5]; // arr[i][j] 表示第i行第j列的值(0≤i≤4, 0≤j≤4-i) // DFS遍历每个门电路位置,尝试三种操作 void dfs(int i, int j) { // 终止条件:已经处理完所有10个门电路(i从1到4,共4+3+2+1=10个) if (i == 5) { if (arr[4][0] == 1) ans++; // 检查最终输出是否为1 return; } // 计算下一个要处理的位置 int x = i, y = j + 1; if (y > 4 - x) { // 如果j超出当前行的范围(第i行有5-i个元素) x++; // 转到下一行 y = 0; // 从下一行的第0列开始 } // 当前门电路的两个输入 int u = arr[i-1][j]; // 左上方的值 int v = arr[i-1][j+1]; // 右上方的值 // 尝试三种门电路,分别递归 arr[i][j] = u & v; dfs(x, y); // 与门 arr[i][j] = u | v; dfs(x, y); // 或门 arr[i][j] = u ^ v; dfs(x, y); // 异或门 } int main() { // 初始化第0层(输入层) arr[0][0] = arr[0][2] = arr[0][4] = 1; // In[0]=1, In[2]=1, In[4]=1 // arr[0][1] 和 arr[0][3] 默认为0(全局变量初始化为0) dfs(1, 0); // 从第1行第0列开始填门电路 cout << ans << endl; return 0; }