【算法每日一练]-dfs (保姆级教程 篇9) #俄罗斯方块 #ABC Puzzle #lnc的工资

目录

今日知识点:

二维图形的状态压缩,存下所有的合法状态然后暴力遍历

dfs的优化剪枝

二项式定理

俄罗斯方块

ABC Puzzle

lnc的工资


        

                

俄罗斯方块

322D

题意:在4*4方格中分别给出3个俄罗斯方块,问是否可以经过旋转,平移操作恰好拼满整个4*4格子? 不能重叠和越界。

输入样例:

样例解释 

思路:

首先是如何存储图形以及变化后的图形,当然不仅要方便变换还要方便最后检查。然后就想到了状态压缩,一共最多16格子,最多需要16位就行。
也就是最大用2^16-1的数字即可表示这种状态,然后对3个俄罗斯方块一一组合遍历看看能否最4*4方格进行平铺。
    如何存入状态:4*4每个格子一一对应1~16的位置,有效的格子坐标转换到一维的二进制位置进行更新。(1<<?和二进制数字相或)平移操作就是把所有位置移动一下。旋转不过是对原字符串进行适当变化,然后把所有的变换后的有效状态存下来。
    如何遍历结果:将3个状态数字相或,然后看是否全是1即可,判断是否等于1<<(4*4)-1就行
要注意不能有重叠:任意两个状态数字不能相与必须为0

非常好的一道状态压缩题!!!

#include <bits/stdc++.h>
using namespace std;
const int SIZE=4;
void rotate(string s[]){//旋转函数(顺时针旋转)char tmp[SIZE][SIZE];for(int i=0;i<SIZE;i++){for(int j=0;j<SIZE;j++){tmp[j][SIZE-1-i]=s[i][j];//i为0时:tmp[0,1,2][2]=s[0][0,1,2]}//相当于横着的变成竖着的}for(int i=0;i<SIZE;i++){s[i]=string (tmp[i],tmp[i]+SIZE);//string函数:从第一个字符位置开始转换,长度位SIZE}
}
bool valid(int x){return x>=0&&x<SIZE;}
int get(string s[],int dx,int dy){int ret=0;for(int x=0;x<SIZE;x++){for(int y=0;y<SIZE;y++){if(s[x][y]=='#'){int xx=x+dx,yy=y+dy;if(!valid(xx)||!valid(yy)){//不能越界,函数重用嘛return -1;}ret |=1<<(xx*4+yy);//xx*4+yy是把每个对应格子给算成数字,然后和ret或运算修改对应位置(有1出1)}}}return ret;
}
vector<int>add(){vector<int>ret;//用于存放状态string s[SIZE];for(int i=0;i<SIZE;i++)cin>>s[i];//输入字符阵列for(int num=0;num<4;num++){//执行四个旋转操作for(int dx=-3;dx<=3;dx++){//执行平移操作,要注意的是不仅要向右平移,还要向左平移for(int dy=-3;dy<=3;dy++){//向上和下平移int v=get(s,dx,dy);//用一个数字来存下次时旋转和平移后的结果(1~16个1的状态,只需要16位即可最多2^16-1)if(v>=0){ret.push_back(v);}}}rotate(s);//旋转一下}return ret;//返回这个俄罗斯方块对应的全部状态
}
int main(){vector<int>mask[3];for(int id=0;id<3;id++){mask[id]=add();//输入字符阵列,获取四个方向,所有平移结果的状态数字,存入mask中}for(int x:mask[0]){//检查所有的情况有没有能成立的for(int y:mask[1]){for(int z:mask[2]){if((x|y|z)+1!=(1<<SIZE*SIZE))continue;//x|y|z就可以把1的位置全部标出来(要等于2^16-1嘛)if(x&y)continue;if(x&z)continue;if(z&y)continue;cout<<"Yes\n";return 0;}}}cout<<"No\n";
}

        

         

ABC Puzzle

326D

题意:给两个长n的仅由ABC组成的字符串s1,s2,是否在n*n阵列中满足以下条件,若满足则输出,不满足输出No

  条件1:每行每列仅包含一个A,一个B,一个C           (3<=n<=5)
  条件2:第i行最左边的字符恰好是s1的第i个字符
  条件3:第i列最上边的字符恰好是s2的第i个字符

输入样例:             输出样例:
5                             Yes
ABCBC                    AC..B
ACAAB                    .BA.C
                                C.BA.
                                BA.C.
                                ..CBA
思路:

一道比较恶心的dfs题。

说一下dfs思路吧:

依次放每个格子可以放.  也可以放A或B或C这四种选择。然后全部放完就检查一下即可。因为走错就要回溯,这最大妥妥的4^25根本过不去。首先主要到每行每列最多两个. 那么就要加以剪枝。

设置cnt[0][i][?]表示第i行已经有几个. 字符,cnt[1][i][?]对应第i列已经有几个. 字符?(剪枝1)

if(cnt[0][x]['.']<n-3&&cnt[1][y]['.']<n-3){//这是放"."的情况,每行列最多放两个,因为只放一次,所以if语句即可an[x][y]='.';cnt[0][x]['.']++;cnt[1][y]['.']++;dfs(x,y+1);cnt[0][x]['.']--;cnt[1][y]['.']--;}

 然后是放置3种字母。首先是看看同行是否已经有该字符。同样设置cnt[0][x][c]代表第x行是否有该字符,cnt[1][y][c]代表第y行是否有该字符。(剪枝2)

        接着是看是否和原字符串的对应位置匹配。第一个字符串对应x行,第二个字符串对应y列,我们如果swap后如果传入的是s[0][x]是0,那么自动返回1,这种情况就对应已经有了开头字符了。如果没有开头字符那就直接和开头字符比较看是否相同。(剪枝3)

for(char c='A';c<='C';c++){//放3种字母if(cnt[0][x][c]==0&&cnt[1][y][c]==0){//第x行y列是否都没有该字符if(match(s[0][x],c)&&match(s[1][y],c)){
//开头都确定,开头一个确定另一个不确定但相等,开头都不确定但都相等an[x][y]=c;char tmp=0,tmp2=0;swap(tmp,s[0][x]);//0和0交换(开头已经确定),0和非0交换(开头未确定变已确定)swap(tmp2,s[1][y]);cnt[0][x][c]++;cnt[1][y][c]++;dfs(x,y+1);cnt[1][y][c]--;cnt[0][x][c]--;//失败,回溯(回溯尽量去swap,这样更容易恢复状态)swap(tmp,s[0][x]);//交换回来swap(tmp2,s[1][y]);}}}

好了,经过以上的剪枝,这个dfs就能过去了 

#include <bits/stdc++.h>
using namespace std;
int n;
int cnt[2][5][128];//cnt[0][i][?]表示第i行已经有几个?字符(ASCII),cnt[1][i][?]对应相关列
char an[5][7];//答案阵列
string s[2];
bool match(char c1,char c2){if(!c1)return 1;//如果说传过来的s[0,1][?]对应第?行,列已经有开头字符了(将会传过来0),那就直接返回正确return c1==c2;//否则就去比较这两个字符
}
//void型dfs 中return其实可有可无,其实就相当于是函数的continue功能,是为了防止进入走后面的代码,引发错误!
//dfs中的标记变量,一定要设置为局部变量,避免被别的dfs给修改
void dfs(int x,int y){//其实每个格子都有4种选择,不见得非ABC就要回溯,一定要细心if(x==n){cout<<"Yes\n";for(int i=0;i<n;i++)cout<<an[i]<<'\n';exit(0);//任务完全直接结束}if(y==n){dfs(x+1,0);return ;}if(cnt[0][x]['.']<n-3&&cnt[1][y]['.']<n-3){//这是放"."的情况,每行列最多放两个,因为只放一次,所以if语句即可an[x][y]='.';cnt[0][x]['.']++;cnt[1][y]['.']++;dfs(x,y+1);cnt[0][x]['.']--;cnt[1][y]['.']--;}for(char c='A';c<='C';c++){、、放3种字母if(cnt[0][x][c]==0&&cnt[1][y][c]==0){//第x行y列是否都没有该字符if(match(s[0][x],c)&&match(s[1][y],c)){
//开头都确定,开头一个确定另一个不确定但相等,开头都不确定但都相等an[x][y]=c;char tmp=0,tmp2=0;swap(tmp,s[0][x]);//0和0交换(开头已经确定),0和非0交换(开头未确定变已确定)swap(tmp2,s[1][y]);cnt[0][x][c]++;cnt[1][y][c]++;dfs(x,y+1);cnt[1][y][c]--;cnt[0][x][c]--;//失败,回溯(回溯尽量去swap,这样更容易恢复状态)swap(tmp,s[0][x]);//交换回来swap(tmp2,s[1][y]);}}}
}
int main(){cin>>n;for(int i=0;i<2;i++)cin>>s[i];dfs(0,0);cout<<"No\n";
}

        

        

lnc的工资

326E

题意:Inc的工资:给出n面的骰子,i对应a[i]元。问最终获得钱的期望是多少(结果对998244353取模)

规则如下:起初x=0,掷出y(>x)则给出a[y]元,同时x变成y,重复操作,直到y(<=x)时结束游戏

思路:

我们先算出现i的概率:
对于第一次:必然是1/n;
第二次:只能从1~i-1过来,所以是(i-1)/n*(1/n),化简成(i-1)*1/n^2
第三次:前两次都恰好从1~i-1中选了两个数,所以是C(2,i-1)*1/n^3   依次类推

然后所有概率相加:∑(i-1,k=0) (1/n)*C(k,i-1)*(1/n)^k    

根据二项式定理转成∑(i-1,k=0) ((n+1)/n)^(i-1) 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=998244353;
ll qpow(ll a,ll b){ll res=1;a%=MOD;while(b){if(b&1)res=(res*a)%MOD;a=(a*a)%MOD;b>>=1;}return res%MOD;
}
ll niyuan(ll x){return qpow(x,MOD-2);
}
int main(){int n;cin>>n;ll nn=niyuan(n);//nn为n的逆元,相当于1/nll now=nn;//now即为当前的概率,最开始now就是i=1的概率ll ans=0;for(int i=1;i<=n;i++){int x;cin>>x;//输入每个a[i]ans=(ans+now*x)%MOD;//累加每个a[i]的期望now=now*(n+1)%MOD*nn%MOD;//求下一个a[i]的概率,只需要多乘一次(n+1)/n,也就是(n+1)*nn即可}	cout<<ans<<'\n';
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/611196.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C++动态内存管理

文章目录 前言1.C/C内存分布2.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free3.C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型 4. operator new与operator delete函数4.1 operator new与operator delete函数 5. new和delete的实现原…

软件测试|MySQL BETWEEN AND:范围查询详解

简介 在MySQL数据库中&#xff0c;使用BETWEEN AND操作符可以进行范围查询&#xff0c;即根据某个字段的值在指定范围内进行检索数据。这个操作符非常有用&#xff0c;因为它可以让我们轻松地筛选出位于两个特定值之间的数据&#xff0c;而不需要使用复杂的条件语句。 BETWEE…

数据挖掘在制造业中的预测与优化应用

随着大数据时代的到来&#xff0c;数据挖掘技术在各行各业的应用日益广泛&#xff0c;尤其在制造业中&#xff0c;其对于提升生产效率、降低运营成本、优化供应链管理等方面发挥着不可替代的作用。本文将探讨数据挖掘在制造业中的预测与优化应用&#xff0c;通过深入剖析实际案…

如何选择最适合的采购付款 (P2P) 解决方案?

无论企业的业务流程执行得如何&#xff0c;流程中始终存在改进空间。更好的管理系统是获得更好结果的关键&#xff0c;尤其是当企业处于增长阶段时。强大的采购到付款&#xff08;P2P&#xff09;系统是加快采购流程&#xff0c;同时保持采购支出可见性的最有效方法之一。 什么…

尚硅谷vite+vue3 (尚医通)项目实战笔记

如何配置项目运行后自动打开&#xff1f; 在package.json 启动命令中添加 “dev”: “vite --open”, 如何配置src的别名&#xff1f; 利用node内置模块path设置一下在vite.config.ts 中的别名 import { defineConfig } from vite import vue from vitejs/plugin-vue import …

IPv6路由协议---IPv6动态路由(OSPFv3-4)

OSPFv3的链路状态通告LSA类型 链路状态通告是OSPFv3进行路由计算的关键依据,链路状态通告包含链路状态类型、链路状态ID、通告路由器三元组唯一地标识了一个LSA。 OSPFv3的LSA头仍然保持20字节,但是内容变化了。在LSA头中,OSPFv2的LS age、Advertising Router、LS Sequence…

Vue3技术解析(小册子)

随着 Vue 3 正式版本的发布&#xff0c;未来 Vue 3 将会成为前端的主流框架&#xff0c;这个毋庸置疑。Vue 3 在使用方面会兼容部分 Vue 2.x 的特性&#xff0c;比如 options API。 所以&#xff0c;究竟是要先学习 Vue 2 打好基础&#xff0c;还是直接学习 Vue 3 呢&#xff…

职场日常英语口语,成人英语培训学校,柯桥学英语推荐哪里

“玩手机”用英语怎么说&#xff1f;你的第一反应是不是&#xff1a;play the phone&#xff1f; 在英语中&#xff0c;play这个动词通常表示“玩耍、娱乐、操纵”等意思&#xff0c;而手机是一种工具&#xff0c;不是玩耍的对象。 换句话说&#xff0c;我们“玩手机”&#xf…

主食冻干哪款好?十大放心主食冻干名单推荐

作为养猫的人&#xff0c;我们都知道每天最担心的事情就是如何为心爱的猫咪选择一款高品质的猫粮。我们都希望为猫咪提供最好的营养&#xff0c;让它们健康快乐地成长。然而&#xff0c;近期的一些事件&#xff0c;如百利猫粮生虫和VE主食冻干掰开有虫&#xff0c;让我们不得不…

软件测试|Windows系统配置pytest+allure环境教程

前言 allure可以输出非常精美的测试报告&#xff0c;也可以和pytest进行完美结合&#xff0c;不仅可以渲染页面&#xff0c;还可以控制用例的执行。本文我们将介绍Windows系统中如何配置allure环境。 第一步&#xff1a;配置Java环境 因为allure的运行依赖于Java环境&#x…

Spring Security介绍

一、Spring Security&#xff1a; 1、简介&#xff1a;Spring Security 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架&#xff0c;提供了一套 Web 应用安全性的完整解决方案。一般来说&#xff0c;Web 应用的安全性包括用户认证&#xff08;A…

vue3引用类型和基础类型深度克隆

深度克隆失效的一个例子 import { cloneDeep } from "lodash"; import { ref } from "vue";const navArr ref(["recommend","hot","new", ]) const list1: any ref([]) const list2: any ref([]) const list3: any ref(…

如何设置电脑桌面提醒,电脑笔记软件哪个好?

对于大多数上班族来说&#xff0c;每天要完成的待办事项实在太多了&#xff0c;如果不能及时去处理&#xff0c;很容易因为各种因素导致忘记&#xff0c;从而给自己带来不少麻烦。所以&#xff0c;我们往往会借助一些提醒类的软件将各项任务逐一记录下来&#xff0c;然后设置上…

手持终端PDA定制厂家_5G安卓手持机设备/条形码扫描手持机PDA

手持终端PDA是一种功能强大的手持终端设备&#xff0c;具备一维码和二维码扫描功能&#xff0c;广泛应用于门票管理、零售、智能巡检、仓储物资管理、金融、快递等领域。 这款手持终端基于MT6877方案&#xff0c;搭载八核处理器(2xCortex-A78 2.4GHz 6xCortex-A55 2.0GHz)&…

高速PCB设计10大要点总结

学习高速PCB设计&#xff0c;掌握这10个知识点很重要&#xff01; 在高速PCB设计的学习中&#xff0c;有很多的知识点需要大家去了解和掌握&#xff0c;比如常见的信号完整性、反射、串扰、电源噪声、滤波等。本文和大家分享10个和高速PCB设计相关的重要知识&#xff0c;希望对…

ChatGPT4+Python近红外光谱数据分析及机器学习与深度学习建模进阶应用

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其在…

最新GPT4、AI绘画、DALL-E3文生图模型教程,GPT语音对话使用,ChatFile文档对话总结

一、前言 ChatGPT3.5、GPT4.0、GPT语音对话、Midjourney绘画&#xff0c;文档对话总结DALL-E3文生图&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和…

【轮式移动机器人课程笔记 5】运动学仿真

L5 运动学仿真 本节重点&#xff1a; 如何理解推导出的运动学模型 回顾&#xff1a;机器人运动学模型 正向&#xff08;前向&#xff09;运动学模型反向运动学模型 基于MatLab运动学仿真 本节重点&#xff0c;如何利用matlab对运动学进行仿真 5.1 回顾运动学模型 [ x ˙ y …

离线AI聊天清华大模型(ChatGLM3)本地搭建

在特定的情况下&#xff0c;要保证信息安全的同时还能享受到AIGC大模型带来的乐趣和功能&#xff0c;那么&#xff0c;离线部署就能帮助到你&#xff0c;最起码&#xff0c;它是一个真正可用的方案。 大模型本身清华的 (ChatGLM3)&#xff0c;为的是对中文支持友好&#xff0c…

Unity Editor实用功能:Hierarchy面板的对象上绘制按按钮并响应

目录 需求描述上代码打个赏吧 需求描述 现在有这样一个需求&#xff1a; 在Hierarchy面板的对象上绘制按钮点击按钮&#xff0c;弹出菜单再点击菜单项目响应自定义操作在这里的响应主要是复制对象层级路路径 看具体效果请看动图&#xff1a; 注&#xff1a; 核心是对Edito…