集训第二天,九道搜索题(据说)我就做了四道……(绝对不是因为不会而是因为没有时间了嚯呀QAQ)
本着好好学习天天向上的想法,我觉得还是要把这些题目落实一下的对吧,所以我这个蒟蒻又来不要脸地写博客啦QWQ
其实今天的题目还挺简单的……?反正考试的时候我是这么想的,但是成绩出来之后彻底击败了我不切实际的幻想(前面我做了的几道题是真的简单但后面那些我没做的估计给我时间我也做不出)
好啦不废话了,还是要整理一下这些题目的嚯呀!
T1 黑白棋游戏 题目传送门
题目大意:已知一个4×4的01矩阵的初始状态和最终状态,求最少移动多少步可以从初始状态变为最终状态。
T2 乌龟棋 题目传送门
题目大意:一行n个格子,每个格子有一个分数值。有m张卡片,上面标着1~4的正整数,代表一次走的格子数。现在要从第一个格子走到最后一个格子,求最大分数值。
T3 CF-177-A
题目大意:求一个长为n的字母序列,其中有k种字母,相邻两个字符不同,同时要求字典序最小。
题目很简单,真的其实都不要用搜索,直接手切(dalao说这道题要是不会做可以考虑退组了),所以我就偷懒一点直接跳过吧……
但是有一点值得一提,那就是考试的时候很坑爹地没有说k=1时要输出-1,所以很多人就这样被卡在了90分(我只有80QAQ因为我没有考虑n=1的情况……)
T4 虫食算 题目传送门
题目大意:给你一个n进制的加法运算,其中的数字都用大写字母来代替,求每个大写字母代表的数字。
这是一道很经典(应该吧我是这么觉得的)的深搜题,之前备战NOIP的时候我就做过了,所以这次很幸运的A掉了。
还是讲一下我的思路吧,因为我发现我今天一开始做的时候其实记得不是很清楚了,还是要再巩固一下。
首先总思路肯定是搜索,那么应该怎么搜呢?
我的思路是列举每个字母可能对应的数字,每个字母都对应了之后验证是否成立。
当然光是这样肯定是过不了的,那就要剪枝啦,剪枝又该怎么剪嘞?
因为两个加数与和的位数是一样的,所以最高位肯定没有进位。其实好像这样就够了,每对应一个字母就带进去验证一下,相当于是一边列举一边验证,这
样也可以算是剪枝。还有要注意的就是一定要逆序!顺序的话会过不了QWQ
这样就可以轻松AC啦~\(≧▽≦)/~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,sum[30],wait[30]; 4 char s1[30],s2[30],s3[30]; 5 bool used[30]; 6 void print(){ 7 for(int i=0;i<n;i++){ 8 if(i==0) printf("%d",sum[i]); 9 else printf(" %d",sum[i]); 10 } 11 exit(0); 12 } 13 bool cut(){ 14 if(sum[s1[0]-'A']+sum[s2[0]-'A']>=n) return 0;//如果第一位要进位显然不可能 15 for(int i=n-1;i>=0;i--){ 16 int A=sum[s1[i]-'A'],B=sum[s2[i]-'A'],C=sum[s3[i]-'A']; 17 if(A==-1||B==-1||C==-1) continue; 18 if((A+B)%n!=C&&(A+B+1)%n!=C) return 0; 19 //如果当前这一位加起来的数字不对,那么也要返回 20 } 21 return 1;//如果符合条件则返回1 22 } 23 bool pd(){//判断是否成立 24 int x=0;//x记录进位 25 for(int i=n-1;i>=0;i--){ 26 int A=sum[s1[i]-'A'],B=sum[s2[i]-'A'],C=sum[s3[i]-'A']; 27 if((A+B+x)%n!=C) return 0; 28 x=(A+B+x)/n; 29 } 30 return 1; 31 } 32 void search(int x){//当前匹配到第x个字母的数字 33 if(!cut()) return; 34 if(x==n){ 35 if(pd()) print(); 36 return; 37 } 38 for(int i=n-1;i>=0;i--){ 39 if(used[i]) continue;//如果这个数字已经和某个字母匹配过就跳过 40 used[i]=1; 41 sum[wait[x]]=i; 42 search(x+1);//继续匹配下一个字母 43 used[i]=0; 44 sum[wait[x]]=-1;//回溯 45 } 46 return; 47 } 48 int num=0; 49 void get(int x){ 50 if(used[x]==0){ 51 used[x]=1; 52 wait[num++]=x;//把需要对应数字的字母找出来记录好 53 return; 54 } 55 } 56 int main(){ 57 freopen("alpha.in","r",stdin); 58 freopen("alpha.out","w",stdout); 59 cin>>n; 60 memset(sum,-1,sizeof(sum)); 61 scanf("%s",s1); 62 scanf("%s",s2); 63 scanf("%s",s3); 64 for(int i=n-1;i>=0;i--){ 65 get(s1[i]-'A'); 66 get(s2[i]-'A'); 67 get(s3[i]-'A'); 68 } 69 memset(used,0,sizeof(used));//标记清零 70 search(0); 71 return 0; 72 }
T5 单词矩阵
题目大意:把A~Y的排列从上到下把 A 到 Y 的排列从上到下从左至右依次填入一个 5 × 5 的矩阵,如果每行每列都递增,则称这个排列是优美的。任务一,给一个排列,求这是第几个优美排列;任务二,给一个数字k,求第k个优美排列。
我看题的时候感觉好像不是很难?但是dalao们的分数让我怀疑自己了……所以这道题最后还是没有搞懂要怎么做,先溜去研究一下题解。
后面几道题目先咕着吧,晚自习再来接着写QWQ。