吉利矩阵
题目大意
dfs思路
- 搜索策略:每一行每一行的搜索,(1,1)->(1,2)->...->(1,n)->(2,1)->...(n,n)
- 剪枝策略:记录每一行与每一列的总和,sumRow,sumCol,接下来要填的数要小于等于 l - sumRow[x] 与 l - sumCol[y],如果当前行填完了,要判断当前行sumRow[x]是否等于 l。
题目代码
#include<bits/stdc++.h>
using namespace std;
int g[5][5],sumRow[5],sumCol[5];
int l,n,cnt;
void dfs(int x,int y){
if(x == n + 1){
++cnt;return;
}
for(int i = 0;i <= min(l - sumRow[x],l - sumCol[y]);++i){
sumRow[x] += i;sumCol[y] += i;
if(y < n) dfs(x,y + 1);
else if(y == n && sumRow[x] == l) dfs(x + 1,1);
sumRow[x] -= i;sumCol[y] -= i;
}
}
int main(){
cin >> l >> n;
dfs(1,1);
cout << cnt << '\n';
}
类似题目
题目链接
https://atcoder.jp/contests/abc326/tasks/abc326_d
题目代码1
#include<bits/stdc++.h>
using namespace std;
int n;string r,c;
vector<bool>lft(6,false),top(6,false);
vector<int>row(6,0),col(6,0);
vector<vector<char>>g(6,vector<char>(6,'.'));
bool flag = false;
void dfs(int x,int y){
if(flag) return;
if(x == n){
for(int i = 0;i < n;++i) if(row[i] != 7) return;
for(int j = 0;j < n;++j) if(col[j] != 7) return;
cout << "Yes" << '\n';
for(int i = 0;i < n;++i){
for(int j = 0;j < n;++j){
cout << g[i][j];
}
cout << '\n';
}
flag = true;
return;
}
bool lleft = lft[x],ttop = top[y];
for(int i = 0;i < 3;++i){
char v = 'A' + i;
if((row[x] >> i) & 1 || (col[y] >> i) & 1) continue;
if(!ttop){
if(c[y] != v) continue;
else top[y] = true;
}
if(!lleft){
if(r[x] != v) {
// 这里也要复原,不然就WA了,找了半天!
top[y] = ttop;
continue;
}
else lft[x] = true;
}
row[x] |= (1 << i);col[y] |= (1 << i);g[x][y] = v;
if(y == n - 1){
if(row[x] == 7) dfs(x + 1,0);
}else dfs(x,y + 1);
lft[x] = lleft;top[y] = ttop;
row[x] ^= (1 << i);col[y] ^= (1 << i);g[x][y] = '.';
}
if(y == n - 1){
if(row[x] == 7) dfs(x + 1,0);
}else dfs(x,y + 1);
}
int main(){
cin >> n >> r >> c;
dfs(0,0);
if(!flag) cout << "No\n";
return 0;
}
题目代码2
#include<bits/stdc++.h>
using namespace std;
int n;string r,c;
vector<vector<string>>row(3);
vector<string>g;
bool flag;
void dfs(int i,int x){
if(flag) return;
if(i == n){
if(x == 0){
cout << "Yes\n";
for(auto &nx:g) cout << nx << '\n';
flag = true;
}
return;
}
for(auto &nx:row[r[i] - 'A']){
g.push_back(nx);
int tmp = x;
bool flag1 = true;
for(int j = 0;j < n;++j){
if(nx[j] == '.') continue;
int y = nx[j] - 'A';
// y已经被选过了
if((x & (1 << (4 * j + y))) == 0) {
flag1 = false;break;
}
tmp ^= (1 << (4 * j + y));
// 判断y是否是填的第一个数字,如果是的话,一定要等于c[j]!
if((x & (1 << (4 * j + 3))) != 0){
if(nx[j] != c[j]) {
flag1 = false;break;
}
tmp ^= (1 << (4 * j + 3));
}
}
if(flag1) dfs(i + 1,tmp);
g.pop_back();
}
}
int main(){
cin >> n >> r >> c;
string abc = "ABC";
while(abc.size() < n) abc.push_back('.');
sort(abc.begin(),abc.end());
do{
char tmp;
for(auto x:abc){
if(x != '.'){
tmp = x;break;
}
}
row[tmp-'A'].push_back(abc);
}while(next_permutation(abc.begin(),abc.end()));
dfs(0,(1 << (4 * n)) - 1);
if(!flag) cout << "No\n";
return 0;
}
标签:abc,return,int,dfs,2024,flag,搜索,天梯,题目
From: https://www.cnblogs.com/gebeng/p/18152426