By 三石吖 2026.2
-
本章节有点困难,只写了一部分,剩下有空再补吧
-
搜索,太困难了!
5.搜索算法
8600 骑士问题
正常广搜即可,没啥坑点
- 时间复杂度,为测试组数
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
constexpr int dx[] = {1, 2, 2, 1, -1, -2, -2, -1};
constexpr int dy[] = {-2, -1, 1, 2, -2, -1, 1, 2};
void solve(){
int b;
int num = 0;
while(1){
num++;
std::cin >> b;
if(b == -1){
return;
}
std::vector<std::vector<int>>a(8, std::vector<int>(8));
for(int i = 0; i < b; i++){
char c;
int r;
std::cin >> c >> r;
a[8 - r][c - 'a'] = 1;
}
int sr, sc, er, ec;
char c1, c2;
std::cin >> c1 >> sr >> c2 >> er;
sr = 8 - sr, er = 8 - er;
sc = c1 - 'a', ec = c2 - 'a';
std::queue<pii>que;
std::vector<std::vector<int>>vis(8, std::vector<int>(8));
vis[sr][sc] = 1;
que.push({sr, sc});
int min = -1;
int cnt = 0;
while(!que.empty()){
int siz = que.size();
for(int k = 0; k < siz; k++){
int x = que.front().first, y = que.front().second;
que.pop();
if(x == er && y == ec){
min = cnt;
break;
}
for(int i = 0; i < 8; i++){
int r = x + dx[i], c = y + dy[i];
if(r >= 0 && r < 8 && c >= 0 && c < 8 && !a[r][c] && !vis[r][c]){
vis[r][c] = 1;
que.push({r, c});
}
}
}
if(min != -1){
break;
}
cnt++;
}
if(min == -1){
std::cout << "Board " << num << ":not reachable\n";
}else{
std::cout << "Board " << num << ":" << min << " moves\n";
}
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
8603 子集和问题
这题直接爆搜就能过,感觉很没有道理
如果是输出任意一种方案的话,直接做背包然后找一下方案即可
搜索做法看看就行了
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n, c;
std::cin >> n >> c;
std::vector<int>a(n);
for(int i = 0; i < n; i++){
std::cin >> a[i];
}
std::vector<int>ans, p;
auto dfs = [&] (auto &&self, int sum, int inx) -> bool {
if(sum == c){
ans = p;
return true;
}
if(inx >= n){
return false;
}
p.push_back(a[inx]);
if(self(self, sum + a[inx], inx + 1)){
return true;
}
p.pop_back();
if(self(self, sum, inx + 1)){
return true;
}
return false;
};
if(dfs(dfs, 0, 0)){
for(auto c : ans){
std::cout << c << " ";
}
std::cout << "\n";
}else{
std::cout << "No Solution\n";
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
8604 运动员最佳配对问题
发现其实并不太能贪心,而数据范围极小,于是考虑搜索
在搜索时,我们实际只需要开一个数组男运动员或女运动员的编号,然后跑全排列即可,另外一组固定为这样,就能不重不漏地跑完了
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n;
std::cin >> n;
std::vector<std::vector<int>>P(n, std::vector<int>(n));
std::vector<std::vector<int>>Q(n, std::vector<int>(n));
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
std::cin >> P[i][j];
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
std::cin >> Q[i][j];
}
}
std::vector<int>a(n);
for(int i = 0; i < n; i++){
a[i] = i;
}
int ans = 0;
do{
int tmp = 0;
for(int i = 0; i < n; i++){
tmp += P[a[i]][i] * Q[i][a[i]];
}
ans = std::max(ans, tmp);
}while(std::next_permutation(a.begin(), a.end()));
std::cout << ans << "\n";
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
11089 多机最佳调度
(1)贪心:让耗时最多的工作给最早空闲的机器,维护一个小根堆即可,复杂度
(2)搜索:枚举每个工作给每台机器的情况,然后剪枝,维护当前能获得的最小答案,如果比这个答案还大的话不进入递归,但这样最劣还是会达到,不知道为啥能过,感觉没啥道理
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n, m;
std::cin >> n >> m;
std::vector<int>t(n);
for(int i = 0; i < n; i++){
std::cin >> t[i];
}
std::sort(t.begin(), t.end(), std::greater<>());
std::priority_queue<int, std::vector<int>, std::greater<>>que;
int ans1 = 0;
for(int i = 0; i < m; i++){
que.push(0);
}
for(int i = 0; i < n; i++){
int x = que.top();
que.pop();
que.push(x + t[i]);
ans1 = std::max(ans1, x + t[i]);
}
std::vector<int>cur(m);
int ans2 = inf;
auto dfs = [&](auto &&self, int inx) -> void {
if(inx >= n){
int tmp = *std::max_element(cur.begin(), cur.end());
ans2 = std::min(ans2, tmp);
return;
}
for(int i = 0; i < m; i++){
if(cur[i] + t[inx] >= ans2){
continue;
}
cur[i] += t[inx];
self(self, inx + 1);
cur[i] -= t[inx];
}
};
dfs(dfs, 0);
std::cout << ans1 << "\n" << ans2 << "\n";
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/
17085 工作分配问题
对人进行全排列然后统计答案
- 时间复杂度
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
using pii = std::pair<int,int>;
using pll = std::pair<i64,i64>;
using pli = std::pair<i64,int>;
using pil = std::pair<int,i64>;
constexpr i64 INF = 0x3f3f3f3f3f3f3f3fll;
constexpr int inf = 0x3f3f3f3f;
void solve(){
int n;
std::cin >> n;
std::vector<std::vector<int>>C(n, std::vector<int>(n));
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
std::cin >> C[i][j];
}
}
std::vector<int>a(n);
for(int i = 0; i < n; i++){
a[i] = i;
}
int ans = inf;
std::vector<int>res;
do{
int sum = 0;
for(int i = 0; i < n; i++){
sum += C[i][a[i]];
}
if(sum < ans){
ans = sum;
res = a;
}
}while(std::next_permutation(a.begin(), a.end()));
std::cout << ans << "\n";
for(int i = 0; i < n; i++){
std::cout << res[i] + 1 << " \n"[i == n - 1];
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef LOCAL
freopen("make.txt", "r", stdin);
freopen("a.txt", "w", stdout);
#endif
int T = 1;
// std::cin >> T;
while(T--){
solve();
}
return 0;
}
/*
*/