首页 > 编程语言 >算法竞赛进阶指南 0x22 深度优先搜索

算法竞赛进阶指南 0x22 深度优先搜索

时间:2022-09-18 15:33:12浏览次数:135  
标签:小猫 进阶 0x22 int 算法 ..... 搜索 缆车 数独

AcWing165. 小猫爬山

翰翰和达达饲养了 N 只小猫,这天,小猫们要去爬山。

经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。

翰翰和达达只好花钱让它们坐索道下山。

索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1、C2CN。

当然,每辆缆车上的小猫的重量之和不能超过 W

每租用一辆缆车,翰翰和达达就要付 1 美元,所以他们想知道,最少需要付多少美元才能把这 N 只小猫都运送下山?

输入格式

1 行:包含两个用空格隔开的整数,NW

2..N+1 行:每行一个整数,其中第 i+1 行的整数表示第 i 只小猫的重量 Ci。

输出格式

输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。

数据范围

1N18,

1CiW108

输入样例:

5 1996
1
2
1994
12
29

输出样例:

2

题解

这道题目使用暴力搜索。

需要表示的状态是

  1. 现在装载哪一只猫咪
  2. 已经使用了多少个缆车
  3. 每一个缆车上装载了多少只猫咪

对于搜索的优化:

  • 如果某一条分支所对应的cnt已经小于目前所发现的最小的缆车数目,那么就直接回溯。
  • 由于总量大的小猫更加难以运送,所以先搜索总量大的小猫。
    由于如果某一种情况上,小车所承载的小猫大于小车所能承载的范围,那么就不再搜索下面的了。如果把重的小猫放在开始,那么就会尽可能多地减去分支。

实现代码

#include <bits/stdc++.h>
using namespace std;
#define N 25
int n;
int a[N];
int cab[N];
int ans;
int vol;
void dfs(int now, int cnt)
{
    //cout << "." << now;
    if(cnt >= ans) return;//最优化剪枝
    if(now == n+1)
    {
        ans = min(ans, cnt);
        return;
    }
    for(int i = 1; i <= cnt; i++)
    {
        if(cab[i] + a[now] <= vol)//可行性剪枝
        {
            cab[i] += a[now];
            dfs(now+1, cnt);
            cab[i] -= a[now];
        
        }
    }
    cab[cnt+1] += a[now];
    dfs(now+1, cnt+1);
    cab[cnt+1] -= a[now];
  
}
int main()
{
    cin >> n >> vol;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", a+i);
    }
    ans = n;
    sort(a+1, a+1+n);//优化搜索的顺序
    reverse(a+1, a+1+n);
    dfs(1, 0);
    cout << ans;
    return 0;
}

AcWing166. 数独

数独 是一种传统益智游戏,你需要把一个 9×9 的数独补充完整,使得数独中每行、每列、每个 3×3 的九宫格内数字 19 均恰好出现一次。

请编写一个程序填写数独。

输入格式

输入包含多组测试用例。

每个测试用例占一行,包含 81 个字符,代表数独的 81 个格内数据(顺序总体由上到下,同行由左到右)。

每个字符都是一个数字(19)或一个 .(表示尚未填充)。

您可以假设输入中的每个谜题都只有一个解决方案。

文件结尾处为包含单词 end 的单行,表示输入结束。

输出格式

每个测试用例,输出一行数据,代表填充完全后的数独。

输入样例:

4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

输出样例:

417369825632158947958724316825437169791586432346912758289643571573291684164875293
416837529982465371735129468571298643293746185864351297647913852359682714128574936

要是完全暴力搜索的话:是\(9^{81} = 1.9662705047555291361807590852691e+77\)

这样显然是不可行的,所以考虑优化:

当全部搜索完后,得到答案;

  1. 可行性剪枝:
    在考虑一个位置的时候,仅往下搜索可行的情况。
    需要排除不可行的情况
  2. 搜索顺序优化:
    先选择可供选择的方案较少的进行。

常数优化:采取位运算的方式。

这道题目的代码量多到令人发指

在我的代码中,把1-9映射成了0-8;

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define N 9
char a[100];
int mp[1<<N];
int ones[1<<N];
int row[N], col[N], cell[3][3];
inline int lowbit(int x)
{
    return x & -x;
}
inline void init()
{
    for(int i = 0; i < N; i++) row[i] = col[i] = (1 << N) - 1;
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
        {
            cell[i][j] = (1 << N) - 1;
        }
}
inline int get(int x, int y)
{
    return row[x] & col[y] & cell[x/3][y/3];
}

bool dfs(int cnt)
{
    if(!cnt) return true;
    int minv = 10;
    int x, y;
    for(int i = 0, k = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++, k++)
        {
            if(a[i*9+j] == '.')
            {
                if(ones[get(i, j)] < minv)
                {
                    minv = ones[get(i, j)];
                    x = i, y = j;
                }
            }
        }
    }
    for(int i = get(x, y); i; i -= lowbit(i))
    {
        int k = mp[lowbit(i)];
//BUG:注意lowbit运算之后仅仅是一个数字
        row[x] -= 1 << k;
        col[y] -= 1 << k;
        cell[x/3][y/3] -= 1 << k;
        a[x*9+y] = k+'1';
      
        if(dfs(cnt-1)) return true;
      
        row[x] += 1 << k;
        col[y] += 1 << k;
        cell[x/3][y/3] += 1 << k;
        a[x*9+y] = '.';
    }
  
    return false;
}

int main()
{
    for(int i = 0; i < N; i++) mp[1 << i] = i;
    for(int i = 0; i < (1<<N); i++)
    {
        int t = 0;
        for(int j = i; j; j -= lowbit(j)) t++;
        ones[i] = t;
    }
    while(scanf("%s", a), a[0] != 'e')
    {
        init();
        int cnt = 0;
        for (int i = 0, k = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++, k++)
            {
                if(a[k] != '.')
                {
                  
                    int t = a[k] - '1';//已经把1到9映射为了0到8
                    row[i] -= 1 << t;
                    col[j] -= 1 << t;
                    cell[i/3][j/3] -= 1 << t;
                }
                else cnt++;
            }
        }

        dfs(cnt);
        printf("%s\n", a);
    }
    return 0;
}

我写的BUG有点多,写代码要很长时间,调BUG也要很长时间!

标签:小猫,进阶,0x22,int,算法,.....,搜索,缆车,数独
From: https://www.cnblogs.com/xjsc01/p/16704876.html

相关文章

  • JAVA进阶--网络通信--2022年9月15日
    第一节  网络编程1、什么是网络编程网络编程可以让程序与网络上的其他设备中的程序进行数据交互2、网络通信基本模式常见的通信模式有如下......
  • 算法中的最优化方法01
    算法中的最优化方法0100课程简介优化尽可能用最佳的方式处理一下事项计算机中基于优化的算法多准则控制器的设计模糊建模中的聚类机器人轨迹规划流程工业中的调度......
  • aardio调用百度云人脸识别(api认证机制authorization算法)
    功能:调用百度云识别里的人脸识别api 这里同时分享给需要的人:namespacebaiduimportinet.urlimporttime.zoneimportcrypt.hmacimportcrypt.binstring=........
  • 道长的算法笔记:动态规划经典模型
    (一)背包模型Waiting...(二)数字三角形模型Waiting...(三)线性规划模型Waiting...(四)区间规划模型Waiting...(五)状态压缩动规模型Waiting.........
  • 为 Transformer 实现形式化算法,第 1 部分:注意力
    为Transformer实现形式化算法,第1部分:注意力边做边学的机器学习。使用DeepMind的伪代码从头开始编写多头注意力的教学实现2017年的论文中介绍了transformer架构注......
  • 【Meetup预告】OpenMLDB+37手游:一键查收实时特征计算场景案例及进阶使用攻略
    2022年9月24日(周六)上午10:00-12:00,开源机器学习数据库OpenMLDB第六期Meetup将通过线上直播的形式展开。活动背景提供生产级实时数据及特征开发全栈解决方案的开源学......
  • 面试常考 算法题
    lz自己遇到的高频题型有:LRU,超高频,lz后面真的是闭着眼睛能写出来的程度了DFS/BFS,最常见的算法,一定要掌握.Waraldи,Union-Find,多次考到双指针/滑动窗口,套路就那么多,但是也......
  • Vue-DIFF算法
    DIFF算法用JavaScript对象结构表示DOM树的结构;然后用这个树构建一个真正的DOM树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。然后用新的树和......
  • 高级前端进阶(六)
    最近有个需求,就是上传图片的时候,图片过大,需要压缩一下图片再上传。需求虽然很容易理解,但要做到,不是那么容易的。这里涉及到的知识有点多,不多说,本篇博客有点重要呀!一、......
  • 报表进阶--参数面板添加
    有时候我们并不需要看所有的数据,比如在销量表中,我们只想看”华北“地区的数据,这个时候我们就需要一个控件能帮助我们过滤掉其他的地区数据。这里我们就要从sql开始设置......