首页 > 其他分享 >2024年3月26号题解

2024年3月26号题解

时间:2024-03-26 22:22:53浏览次数:37  
标签:26 now return int 题解 dfs 2024 path include

Eight II

解题思路

  1. 使用IDA*算法进行搜索,同时遍历所有高度中最小的,再保存dfs中的路径就可以了

代码实现

#include <sstream>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<queue>
#include <set>
using namespace std;
const int N = 100;

int T = 1;
int xb[10];//保存数字状态所在的下标方便计算预估函数
int path[N];//保存路径
string now, endd;//起始状态和终止状态
//对应的操作下标
int dx[4] = { 1, 0, 0, -1 };
int dy[4] = { 0, -1, 1, 0 };
char op[4] = { 'd', 'l', 'r', 'u' };//因为要字典序最小所以按照字典序遍历

//估值函数,当前状态和目标状态每个点的曼哈顿距离差的和
int f()
{
        int res = 0;

        for (int i = 0; i < 9; i++)
        {
                if (now[i] != 'X')
                {
                        int t = now[i] - '0';
                        res += abs(i / 3 - xb[t] / 3) + abs(i % 3 - xb[t] % 3);
                }
        }
        return res;
}


//因为 dfs 是一条路一条路的搜,并且有回溯。
//所以我们只需要一个 path 即可,后面的会覆盖前面的。
//同样 now 状态只需要一个,回溯会返回状态。

int depth;
bool dfs(int u)
{
        //如果当前深度 + 估值深度 > 最大深度 直接回溯
        if (f() + u > depth) return false;
        if (now == endd) return true; //找到答案了 直接return true

        int X;//找到 X 的位置
        for (int i = 0; i < 9; i++)
        {
                if (now[i] == 'X')
                {
                        X = i;
                        break;
                }
        }
        int x = X / 3, y = X % 3;//一维坐标转换成二维坐标

        for (int i = 0; i < 4; i++)
        {
                int zx = x + dx[i], zy = y + dy[i];

                //优化
                //避免无效操作: 上一个为 l 当前为 r,等于没变化
                if (u != 0 && i + path[u - 1] == 3) continue;
                if (zx < 0 || zx >= 3 || zy < 0 || zy >= 3) continue;

                //change
                swap(now[x * 3 + y], now[zx * 3 + zy]);
                path[u] = i;

                if (dfs(u + 1)) return true;
                //回复现场
                swap(now[x * 3 + y], now[zx * 3 + zy]);
        }

        return false;//如果没有一种分支可以得到终点状态就返回false
}

void solved()
{
        cin >> now >> endd;

        //找到目标状态对应的下标
        for (int i = 0; i < 9; i++) xb[endd[i] - '0'] = i;

        for (depth = 0;; depth++) if (dfs(0)) break;//找到第一个符合条件的深度即最短路径

        cout << "Case " << T++ << ": " << depth << endl;
        for (int i = 0; i < depth; i++) cout << op[path[i]];
        cout << endl;

}


int main()
{
        int t;
        cin >> t;
        while (t--)
        {
                solved();
        }
        return 0;
}

哈密顿绕行世界问题

解题方法

  1. dfs直接遍历图再最后判断能不能回到起点可以了

代码实现

#define  _CRT_SECURE_NO_WARNINGS
#include <sstream>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<queue>
#include <set>
#define sc scanf
#define pr printf

using namespace std;

const int N = 21;

//存放走的路径
int path[21];
//链式前向星存图
int cnt = 1;
int head[N];
int to[N * N];
int nxt[N * N];
//一个节点的邻接点
int a[3];
//起点
int m;
//标记数组
int v[N];
//第几条路径
int j = 1;

void dfs(int s, int pos) {
        if (pos == 21 && path[pos - 1] == m) {//如果遍历完了图并且也可以回到起点,那么就打印路径
                pr("%d:  ", j++);
                for (int i = 0; i < pos; i++) {
                        pr("%d ", path[i]);
                }
                pr("\n");
        }

    //遍历节点的边
        for (int i = head[s]; i; i = nxt[i]) {
                if (!v[to[i]]) {
                        path[pos] = to[i];
                        v[to[i]] = 1;
                        dfs(to[i], pos + 1);
                        v[to[i]] = 0;
                }       
        }
}

bool compare(int a, int b)
{
        // 升序排列,如果改为return a>b ,则为降序
        return a > b;
}

void add(int from, int t)
{
        nxt[cnt] = head[from];
        to[cnt] = t;
        head[from] = cnt++;
}

int main() {
        for (int i = 1; i <= 20; i++) {
                sc("%d%d%d", a, a + 1, a + 2);

                sort(a, a + 3, compare);//保证数组是升序的,那么就可以保证输出的时候是字典序最小

                add(i, a[0]);
                add(i, a[1]);
                add(i, a[2]);
        }

        while (sc("%d", &m), m) {
                path[0] = m;
                dfs(m, 1);
                memset(v, 0, sizeof(v));
                j = 1;
        }

        return 0;
}

 

标签:26,now,return,int,题解,dfs,2024,path,include
From: https://www.cnblogs.com/lwj1239/p/18097744

相关文章

  • NKCTF2024
    myfirstcms搜索版本跳转到登录页面爆破出用户密码adminAdmin123Extensions>UserDefinedTags->AddUserDefinedTag一句话木马Run拿到flag全世界最简单的CTF拿到源码格式化constexpress=require('express');constbodyParser=require('body-parser');......
  • 3.26
    今天老师给了我们组队,所以我需要对接下来的一周做一下规划,我帮扶的对象只连接了本地数据库,所以需要教会他连接远程数据库mysql,因为我自己学的是安卓连接后端连接mysql数据库,但是对于他来说这个似乎更麻烦,不巧的是对于安卓直接连mysql我也不太会,所以我还需要自己学,其实也就是对于为......
  • 更新和添加参数校验优化(2024-3-26)
    由于更新文章分类和添加文章分类,参数校验时,一个需要IDnotnull一个只是让id自动增长,所以当再次添加新的文章时会出现id为空的错误:这时候就要用到validation提供的分组校验:把校验项进行分类,在完成不同功能的时候,校验指定组中的校验项packagecom.di.bigevent.pojo;importco......
  • 20240326打卡
    第五周第一天第二天第三天第四天第五天第六天第七天所花时间20h4h代码量(行)877164博客量(篇)11知识点了解navigation路由配置,jetpackcompose组件运用,容器封装第一次结对作业开始今天主要由建民老师包分配的方式给我分了结......
  • 【Azure Service Bus】启用诊断日志来获取客户端访问Azure Service Bus的IP地址 [2024
    问题描述在使用ServiceBus中,遇见了莫名奇妙,不知来源的访问,但是又不敢直接修改AccessKey(担心影响正常业务),所以想通过访问服务的客户端IP地址来分析,到底是那里的客户端在访问ServiceBus服务? 问题解答经过调查,可以通过开启AzureServiceBus的诊断日志来实现此目的。......
  • 联合省选 2024 题解
    魔法手杖考虑判定答案是否可以大于等于\(t\)。观察\(a_i\oplusx<t\)的情况,可以发现满足要求的\(x\)分为若干段:最高\(u\)位为\(a_i\oplust\)的最高\(u\)位;接下来这一位\(t\)为\(1\),且\(x\)取值为\(a_i\)这一位的取值;更低的位随意。这事实上相当于:我们往0......
  • 3.26博客
    作业根据地域属性实现数据的可视化展示,可以看到省-市-区县三级数据下钻呈现的项目数量name为null的时候value显示为NAN因为地图该区域在数据库中没有匹配的name,所以这里count(*)直接为null,显示NAN; b->namec-<value 之前在select那里判空,没用,后来想起了地图部分在数据库......
  • [20240325]FORCE_MATCHING_SIGNATURE与DML.txt
    [20240325]FORCE_MATCHING_SIGNATURE与DML.txt--//生产系统遇到1个FORCE_MATCHING_SIGNATURE重合的奇怪现象,一般情况都是相似的sql语句(没有使用绑定变量的sql语句),--//FORCE_MATCHING_SIGNATURE相同。--//实际上insert语句真实FORCE_MATCHING_SIGNATURE=0,但是在v$active_session......
  • [20240325]expand_sql_text dba_hist_sysstat(12c).txt
    [20240325]expand_sql_textdba_hist_sysstat(12c).txt--//前几天测试dba_hist_sysdate的底层视图定义里面包含提示.--//测试一条sql语句包含dba_hist_sysstat使用expand_sql_text的展开情况.1.环境:SYS@test>@ver1PORT_STRING                   VERSION ......
  • AT_arc174_a [ARC174A] A Multiply的题解
    (一)注意到,\(c\)可能\(<1\)。主要考虑操作后的变化量。当\(c=1\)时,不会改变序列。当\(c>1\)时,和最大即为增加最多。那么求出最大子段和,再乘上\(c-1\)即为变化量。当\(c<1\)时,将序列每个数取反即可。(二)我因为不会最大字段和挂了3发。#include<bits/stdc+......