T1:问题 A: 组合的输出

题目描述

排列与组合是常用的数学方法,其中组合就是从 n 个元素中抽出 r 个元素(不分顺序且 r<=n),我们可以简单地将 n 个元素理解为自然数 1,2,…,n,从中任取 r 个数。
现要求你用递归的方法输出所有组合。
例如 n=5,r=3,所有组合为:
l 2 3 l 2 4 1 2 5 l 3 4 l 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5

输入

一行两个自然数 n、r(1<n<21,1<=r<=n)。

输出

所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。

样例输入

5 3

样例输出

1  2  3

1  2  4

1  2  5

1  3  4

1  3  5

1  4  5

2  3  4

2  3  5

2  4  5

3  4  5

题解

这道题考察了排列数的问题。只需要用一个pd数组来枚举每一层(每一位)选什么数,再用一个VIS数组来记录是否选过,若没选则选,否则下一个。注意可能用快读快写优化时间。

参考代码

#include<cstdio>
using namespace std;
int n,r,x[100],vis[100];
void dfs(int k)
{if(k==r+1){for(int i=1;i<=r;i++)printf("%3d",x[i]);printf("\n");return ;}for(int i=x[k-1]+1;i<=n;i++){if(!vis[i]){vis[i]=1;x[k]=i;dfs(k+1);vis[i]=0;}}
}
int main()
{scanf("%d%d",&n,&r);dfs(1);return 0;
}

T2:问题 B: 门票问题

题目描述

有很多人在门口排队,每个人将会被发到一个有效的通行密码作为门票。一个有效的密码由L(3≤L≤15)个小写英文字母组成,至少有一个元音(a、e、i、o或u)和两个辅音(除去元音以为的音节),并且是按字母表顺序出现的(例如abc是有效的,而bac不是)。
    现在给定一个期望长度为L和C(1≤C≤26)个小写字母,写一个程序,输出所有的长度为L、能由所给顶的C个字母组成的有效密码。密码必须按字母表顺序打印出来,一行一个。

输入

第1行是两个由一个空格分开的正整数,L和C,3≤L≤15,1≤C≤26。
    第2行是C个由一个空格隔开的小写字母密码是由这个字母集中的字母来构建的。

输出

若干行,每行输出一个长度为L个字符的密码(没有空格)。输出行必须按照字母顺序排列。程序只需要输出前25000个有效密码,即使后面还存在有效密码。

样例输入

4 6

a t c i s w

样例输出

acis

acit

aciw

acst

acsw

actw

aist

aisw

aitw

astw

cist

cisw

citw

istw

题解

本题与上一道题相比,多了一些要求:至少一个元音,2个辅音。因此我们可以在搜索的过程中来剪枝。首先可以维护一个前缀和(倒着的),表示后面元音的个数。搜索过程中,如果当前枚举到了k,前面没有元音,而后面也没有元音了(前缀和),那么就可以直接return。同理,辅音的处理与这个类似,只不过是个数<2。同时如果接下来的字母都用上,还达不到既定长度,那么也return。有了3重剪枝,就能极大的优化时间效率。

参考代码

#include<cstdio>
#include<algorithm>
using namespace std;
int l,c,x[100],seg[500],p[100],vis[100],tot=0;
char s[100];int pd1[500],pd2[500],sis=0,ht[500];
bool pd(int k) { return k=='a'||k=='e'||k=='i'||k=='o'||k=='u'; }
void dfs(int k)
{if(tot>25000) return;pd1[k]=pd1[k-1];pd2[k]=pd2[k-1];if(k==l+1){if(pd1[k]==0||pd2[k]<2) return;tot++;if(tot>25000) return;for(int i=1;i<=l;i++)putchar(p[i]);printf("\n");return;}for(int i=seg[p[k-1]]+1;i<=c;i++){if(tot>25000) return;if(vis[i]) continue;if(i==sis&&pd1[k]==0) break;if(pd2[k]+ht[i]<2) break;if(c-i+1+k<l) break;vis[i]=1;p[k]=x[i];if(pd(x[i])) {pd1[k]++;dfs(k+1);pd1[k]--;}else{pd2[k]++;dfs(k+1);pd2[k]--;}vis[i]=0;}
}
int main()
{scanf("%d%d",&l,&c);for(int i=1;i<=c;i++){scanf("%s",s);x[i]=s[0];} sort(x+1,x+c+1);for(int i=c;i>=1;i--) {seg[x[i]]=i;ht[i]=ht[i+1];if(pd(x[i])&&sis==0)sis=i+1;if(!pd(x[i]))ht[i]++;}dfs(1);return 0;
}

T3:问题 C: 子集和问题

题目描述

子集和问题的一个实例为〈S,c〉。其中,S={ x1, x2,…, xn}是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得子集S1和等于c。
对于给定的正整数的集合S={ x1, x2,…, xn}和正整数c,编程计算S 的一个子集S1,使得子集S1和等于c。

输入

第1行有2个正整数n和c,n表示S的个数,c是子集和的目标值。

接下来的1 行中,有n个正整数,表示集合S中的元素。

n<=8000 c<=10^7

输出

子集,各元素之间用空格隔开。当问题无解时,输出“No solution!”。

样例输入

5 10

2 2 6 5 4

样例输出

2 2 6

题解

这道题忽略数据范围吧。现在只考虑怎么完成这道题。同样的,用一个pd数组维护sum,如果sum=c就全部return。当然,还要用x数组记录所选的元素。这样还不够,需要一点小剪枝。如果此刻的sum大于c,return;如果后面的数的和加上sum都小于c,那么也没必要继续搜了,直接return。如此就能找到一组答案就退出,或者输出问题无解。

参考代码

#include<cstdio>
#define LL long long
using namespace std;
int n,c,a[10000],sum=0,sum1[10000];
int pd=0,x[10000];
void dfs(int k)
{if(sum+sum1[n]-sum1[x[k-1]]<c) return;if(pd==1) return;if(sum==c){for(int i=1;i<k;i++) printf("%d ",a[x[i]]);pd=1;return;}for(int i=x[k-1]+1;i<=n;i++){x[k]=i;if(sum+a[i]>c) continue;sum+=a[i];dfs(k+1);sum-=a[i];}
}
int main()
{scanf("%d%d",&n,&c);for(LL i=1;i<=n;i++) {scanf("%d",&a[i]);sum1[i]=sum1[i-1]+a[i];}dfs(1);if(pd==0) printf("No Solution!");return 0;
}

T5:问题 E: 数独

题目描述

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

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

输入

输入包含多组测试用例。

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

每个字符都是一个数字(1-9)或一个”.”(表示尚未填充)。

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

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

输出

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

样例输入

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.

......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.

样例输出

527389416819426735436751829375692184194538267268174593643217958951843672782965341

416837529982465371735129468571298643293746185864351297647913852359682714128574936

题解

对于这道题我也算是颇有心得。我的代码对于单个的九宫格不输任何表答,但就是要跑2s!!所有我这个代码无法过数独这道题(泪流满面,蒟蒻的悲伤~)。现在来谈谈这道题。首先用一个e_map存一下地图,然后把每一行、每一列、每一个3*3方块压缩成二进制保存下来。再把每一行还没有填的格子记录一下(这样就不用重复找已经填过的数),然后就搜呗。

搜的话很简单了,只用在(横着的没填的、竖着的没填的、方块里没填的)求交集,然后枚举数字即可。注意,是!没!填!的!因此我们直接把之前二进制压缩的结果亦或(^)511(二进制111111111)就可以了,相当于全部取个反(现实意义)。处理了这一位的数字后,来考虑下一次枚举那一个位置。这时我就直接用了一个!!!大优化!!!就是每次把每一行能取的位置倒着枚举,然后……直接取,并且把当前行的总共能填的总数-1,并且在回溯之后加回去就可以了。这一步十分精妙,可以动态剪枝,并且由于我的每一行总数组不变,变的只是尾指针,因此答案也是正确的,这部分参见代码中search函数。

为了进一步优化,我还用冒泡排序(个人认为应该用快排,可能会快一些,但是……写不来那种)把每一行的能取的位置排了个序,关键字就是这个位置能填的数的可能性,可能性越小,说明需要回溯的机会越少,也就能越快的找到答案。还有一个明显的优化,就是找到了唯一的一组解后,直接return,并且要让所有正在运行的函数全部return,因此我定义了ed,当ed=1时,表示答案已找到,此时我在大量的区域做了ed的判断(其实就2处),加快return的速度。对于找数字,此处还运用了lowbit的知识来优化选择,有兴趣者可以自行查阅,不用lowbit也能跑,for就行了,但是时间效率就会损失的比较多。

还有一点,用tot存一下此刻还有多少空格没有选,当tot=0时表示答案已经出现,此刻更新ed,并且输出答案。特别注意各个函数的初始化,这点十分重要。至于那几个输出的函数,只是为了验算一些东西,可自行理解。如何处理3*3的块?如果看过代码(…………此处省略一万字),就能发现我的数组的更新就解释了这一点。(x+2)/3能够准确表示这是上中下的那一块区域,同理对于y也能确定在哪一竖行。

代码最后可以计算出单纯dfs的运行时间,我就是通过这个来判断时间的,注意最后的输出毫秒是浮点数,要用ctime的头文件。最后为了提速,还用了各种方法,只是效果皆不明显,此处就省略了。最后注意!!!这代码能很快求一个的答案,却没法过!!!

对了,这个代码最后有很多我自己找的数据,答案可用下面代码对拍。

参考代码

#include<cstdio>
#include<ctime>
#include<iostream>
using namespace std;
char s[2000];int e_map[10][10],tot_x[10],max0=-1,tot=0;
int tick_x[20],tick_y[20],tick_k[5][5],st_x,st_y;
int max1(int p,int q) { return p>q?p:q; }
int ed=0,lg[1025],went[10][10],goes[10];
void outputing()
{for(int i=1;i<=9;i++)for(int j=1;j<=9;j++)printf("%d",e_map[i][j]);printf("\n");
}
void output2()
{for(int i=1;i<=9;i++){for(int j=1;j<=9;j++)printf("%d",e_map[i][j]);printf("\n");    }printf("\n");
}
void output3(int k)
{for(int i=1;i<=9;i++){printf("%d",k%2);k/=2;}printf("\n");
}
int search()
{for(int i=1;i<=9;i++){for(int k=goes[i];k>=1;k--){int j=went[i][k];st_x=i;st_y=j;goes[i]--;return i;//找到一个直接取位置就可以//后面会把goes再加回去}}
}
void dfs(int x,int y)
{if(ed==1) return;if(tot==0){outputing();ed=1;return;}int ttt=tick_x[x]^511;//取反while(ttt){if(ed==1) return;int pk=ttt&-ttt;ttt-=pk;//lowbit取数if((pk&tick_y[y])) continue;if((pk&tick_k[(x+2)/3][(y+2)/3])) continue;//行、列、块不冲突tick_x[x]|=pk;tick_y[y]|=pk;tick_k[(x+2)/3][(y+2)/3]|=pk;//短暂更新地图(行列块)的数据e_map[x][y]=lg[pk];tot--;int rst=search();dfs(st_x,st_y);//把取出来的数“放回去”,关键的一步剪枝goes[rst]++;tot++;tick_x[x]^=pk;tick_y[y]^=pk;tick_k[(x+2)/3][(y+2)/3]^=pk;//回溯需要还原e_map[x][y]=0;}
}
int main()
{lg[1]=1;lg[2]=2;lg[4]=3;lg[8]=4;lg[16]=5;lg[32]=6;lg[64]=7;lg[128]=8;lg[256]=9;//为lowbit的计算做准备while(1){tot=ed=max0=0;scanf("%s",s);if(s[0]=='e') break;for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)tick_k[i][j]=0;//数组初始化for(int i=1;i<=9;i++){goes[i]=0;//每一行尾指针tick_x[i]=0;tick_y[i]=0;for(int j=1;j<=9;j++)went[i][j]=0;}for(int i=1;i<=9;i++)for(int j=1;j<=9;j++){if(s[(i-1)*9+j-1]=='.'){went[i][++goes[i]]=j;//记录每一行合法位置e_map[i][j]=0;tot++;}else {//二进制压缩e_map[i][j]=s[(i-1)*9+j-1]-'0';tick_x[i]|=(1<<(e_map[i][j]-1));tick_y[j]|=(1<<(e_map[i][j]-1));tick_k[(i+2)/3][(j+2)/3]|=(1<<(e_map[i][j]-1));}}//冒泡排序for(int i=1;i<=9;i++)for(int j=1;j<=9;j++)for(int k=1;k<=9;k++)if(went[i][j]>went[i][k]){int c=went[i][k];went[i][k]=went[i][j];went[i][j]=c;}search();//找出初始位置
//          clock_t t;
//      t=clock();dfs(st_x,st_y);
//      t=clock()-t;
//      cout<<"时间为:"<<(((float)t)/CLOCKS_PER_SEC*1000)<<"ms\n";      //记录dfs时间}return 0;
}.................................................................................
.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
1.3...5.9..21.94.....7.4...3..5.2..6.6.....5.7..8.3..4...4.1.....92.58..8.4...1.7
8..........36......7..9.2...5...7.......457.....1...3...1....68..85...1..9....4..
..53.....8......2..7..1.5..4....53...1..7...6..32...8..6.5....9..4....3......97..
98.7..6..7......8...6.5....4....3.....89...7.....2.3...1....2....75...6......1.54
.3...7..46.2.41....5..3.967.4...3..6.87...35.9..7...2.718.2..4....16.8.94..5...3.
..5..43.1..........28..6.4....4.5...7......6.6......3...3...17....1.9.....9..2..8
.6.....75....4..9.8.3........8.9.....72..6...6..4.5...12.6......3..7.2....7..431.
...8......3..92..1.9..3....7...498....57..9..2....6.....352.1...5....4.2..6..4...
43.28...............84...1.9.3..2.4..7..3..2..5.9..8.1.2...65...............41.76
57.12...............67...8.3.4..9.7..2..7..5..1.3..9.2.8...21...............54.63
...6....7...849...28......5..7315....4..7......2......91..8..6.7......9...34..5..
75..9..469.1...3.2.........2..6.1..7.8.....2.1..3.8..5.........3.9...2.484..3..79
end

2021 9.14 p.m.小结 以及 数独问题探索(T3)相关推荐

  1. 2021.8.14【提高B组模拟6】T3 + P7527 [USACO21OPEN] United Cows of Farmer John (树状数组)

    United Cows of Farmer John 题目传送门 解题思路 树状数组乱糊 AC代码 #include<cstdio> #include<cstring> usi ...

  2. 2021.8.8 ~ 2021.8.14 在SSL集训总结(Week 1 已更完)

    集训总结 前言 因为疫情,就回到SSL集训了 (可能有点长,右边有目录) 后续,第二周 2021.8.15 ~ 2021.8.25 在SSL集训总结(Week 2)(更新ing) Day -1(8.7 ...

  3. 电动力学每日一题 2021/10/14

    电动力学每日一题 2021/10/14 (a) Define r∣∣=xx^+yy^\textbf r_{||}=x\hat x+y\hat yr∣∣​=xx^+yy^​, r∣∣=x2+y2r_{| ...

  4. 在使用计算机时遇到什么样的问题,2021年1-4月雅思口语题库part23:你在使用电脑时遇到的问题...

    雅思口语又到了换题季啦,相信你肯定很想知道雅思口语都考哪些题,今天新东方在线小编就给大家整理了2021年1-4月雅思口语题库part2&3:你在使用电脑时遇到的问题,希望能给你的雅思口语备考提 ...

  5. 2021.01.14【NOIP提高B组】模拟 总结

    2021.01.14[NOIP提高B组]模拟 总结 第一题 Candy 奇奇怪怪的题目. 一开始没有理解题目,其实就是同时变换. 打了一个暴力. 本人随机生成50000组数据,都过了,时间没超.希望出 ...

  6. 2021/7/14 java小结

    1.1 类的定义: 类:class. 对象:object. //定义如下: public class 类名 { 修饰符 类型 成员名称;//可以有多个 修饰符 类型 方法名;//可以有多个 } pub ...

  7. 2021年14项世界互联网领先科技成果发布

    来源:桐乡发布 9月26日下午,由国家互联网信息办公室.浙江省人民政府主办的2021年"世界互联网领先科技成果发布活动"在乌镇互联网国际会展中心乌镇厅举行.华为鸿蒙操作系统.北斗卫 ...

  8. 博客新功能上线,可导出PDF……【2021.12.14】

    hello,大家好,这里是「CSDN产品周报」第21期.本次更新主要涉及首页榜单.博客.问答,具体细节请往下看. 一.CSDN榜单优化 1.排行榜导航栏从右侧移动到左侧 2.新增「原力月榜」,选取全站 ...

  9. 2021款14寸MacBook Pro使用体验真实感受

    购买的2021款MacBook Pro是14寸的加配10核心M1 Pro芯片,32g内存,512g存储.已经使用两周了,说说这段时间的使用体验. 1.外观 和2015款的13寸对比,他俩的大小.尺寸. ...

  10. [2021.10.14][Android P]OpenCamera详细分析(Camera2+Hal3)

    因为工作涉及到Android Camera系统的问题,本文整理了在Android P上讲解OpenCamera比较详细的文章,结合Andriod P源码,以架构图.UML顺序图.UML类图和关键代码走 ...

最新文章

  1. 一.Timesten安装
  2. java方法6_6.1 JAVA方法入门
  3. Zabbix监控Nginx性能状态
  4. SolrJ查询索引库
  5. boost::yap::value相关的测试程序
  6. MVC3 URL 数据绑定
  7. 207. 课程表/210. 课程表 II
  8. 如何为JavaScript选择文本编辑器
  9. perl 序列化_对Perl的热爱团结了多元化的社区
  10. 视觉传达对中职计算机教育影响,自考视觉传达设计毕业论文:平面设计专业信息化教学资源库建设...
  11. Atitit mq的AMQP 协议 STOMP2 、MQTT3 等协议  MQTT,XMPP,STOMP,AMQP,WAMP 目录 1. AMQP in a Nutshell 1 2. MQTT概述
  12. 热门加壳工具VMProtect v3.1发布,新增内存保护,性能改进|附下载
  13. 在HTML 页面中如何显示带圈圈的数字
  14. HCP数据的下载,以及头动文件和CSF文件的所在位置
  15. 华为云--云平台部署管理架构图
  16. RACV2022观点集锦 | 视觉基础模型
  17. Microsoft Store无法显示错误,真正解决!
  18. 利用Go制作微信机器人(一)发送消息
  19. pc企业微信协议,企业微信HOOK接口
  20. 品商业模式[摘自xiewen网络业游戏规则]

热门文章

  1. jquery全国省市县三级联动
  2. 分享个B端竞品分析报告
  3. bp神经网络预测模型实例,bp神经网络模型的建立
  4. AppScan 的安装+激活以及+漏扫dvwa,生成安全报告
  5. 桌面云之深信服VDC安装部署和虚拟机模板创建
  6. Java固定资产管理系统源码
  7. Java程序调用OpenDDS
  8. Qt音视频开发41-人脸识别嵌入式
  9. java软件工程师自我评价_Java工程师自我评价如何写?
  10. 如何保护前端JS代码?前端js代码混淆加密