您的位置:首页 > 其它

2018蓝桥杯模拟赛(一)C【模拟】D【dp】E【全排列】F【dfs】

2018-03-27 12:44 441 查看
C.U型数字

最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增。比如 212212212 就是一个U型数字,但是 333333333, 989898, 567567567, 313133131331313,就是不是U型数字。

现在蒜头君问你,[1,100000][1,100000][1,100000] 有多少U型数字?

提示:请不要输出多余的符号。

#include<iostream>
#include<cstring>
using namespace std;
int num[10];
int cnt = 0;
int main()
{
int weishu = 0;
int j;
int flag;
for(int i = 100;i<=99999;i++)
{

memset(num,0,sizeof(num));
int temp = i;
for(j = 0;temp != 0;j++)
{
num[j] = temp%10;
temp = temp/10;
}
weishu = j;
j= 1;
while(num[j]<num[j-1])
{
j++;
}
flag = j;
while(num[j]>num[j-1])
{
j++;
}
//保证两个循环都进去过才能说明存在严格递减和严格递增
if(j == weishu&&j>flag&&flag!=1) //flag!=1保证进入第一个循环 j>flag 保证进入第二个循环
{
cnt++;
//  cout<<i<<' ';
}
}
cout<<cnt<<endl;
}


D LIS

LIS是最长上升子序列。什么是最长上升子序列? 就是给你一个序列,请你在其中求出一段最长严格上升的部分,它不一定要连续。

就像这样:222, 333, 444, 777 和 222, 333, 444, 666 就是序列 222 555 333 444 111 777 666 的两个上升子序列,最长的长度是 444。

#include<iostream>
#include<cstring>
using namespace std;

int f[10000], b[10000];
int lis(int n) {
memset(f, 0, sizeof f);
int res = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (b[j] < b[i]) {
f[i] = max(f[i],f[j]+1); //填空  dp: 每再前面遇到一个小于自己的数,就判断如果加上这个数那么f[i] = f[j]+1,还是不加上这个数保持f[i],选择大的
}
}
res = max(res, f[i]);
}
return res+1;
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", b + i);
}
printf("%d\n", lis(n));
return 0;
}


E 全排列

相信大家都知道什么是全排列,但是今天的全排列比你想象中的难一点。我们要找的是全排列中,排列结果互不相同的个数。比如:aab 的全排列就只有三种,那就是aab,baa,aba。

代码框中的代码是一种实现,请分析并填写缺失的代码。

思路:填空的地方的意思是,如果i的后面有和s[i] 相等且访问过的字符,则不可以(break),一旦break,j 就不能等于len,就不能继续递归。那么怎么理解这个呢?

先想一下简化的问题吧,假如输入的字符串不重复,例如abcd,那么就是简单的dfs了,一个for循环加一个vis判断,如果判断可以,继续递归。

当有重复的字符时候就比较麻烦了,比如aab,单纯的用递归会输出重复的。那么怎么加上限定条件呢。

这里,我们让重复的这些字符只顺序输出一遍,这样就不会重复

这是什么意思呢,比如说aabc,我们只允许第一个a访问后再访问第二个a,不允许访问第二个,再第一个。

再如,abacda,那三个a只能按顺序访问。

原理是什么呢,用了点高中学的排列组合的知识,先排重复的,例如我们搞abacda这个例子, 先排三个a, 就是 aaa,那么剩下的就相当于直接插入到aaa中,那么如果我们aaa如果按多种顺序排,就会产生多种结果,所以只能按顺序访问。

那么又如何用算法实现呢,直接加个if判断就行了,判断i之后的有没有访问过的且相等的。例如,aabc这个例子,我们第一轮选完之后,到了第二个a,然后进入递归,for循环又从0开始,到了第一个a,然后从这个之后去判断有没有访问过的a,结果判断有,违反了顺序,所以结束。

这个题目的关键也就是排除重复的

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e3;
char str
, buf
;//buffer
int vis
, total, len;
void arrange(int num) {
if (num == len){
printf("%s\n", buf);
total++;
return;
}
for (int i = 0; i < len; ++i) {
if (!vis[i]) {
int j;
for (j = i + 1; j < len; ++j) {
//比如递归到buf[1] =
if (str[i]==str[j]&&vis[j])//填空
{
break;
}
}
if (j == len) {
vis[i] = 1;
buf[num] = str[i];
arrange(num + 1);
vis[i] = 0;
}
}
}
}
int main() {
while (~scanf("%s",str)) {
len = strlen(str);
sort(str, str + len);
total = 0;
buf[len] = '\0';
arrange(0);
printf("Total %d\n", total);
}
return 0;
}


蒜头君今天突然开始还念童年了,想回忆回忆童年。他记得自己小时候,有一个很火的游戏叫做数独。便开始来了一局紧张而又刺激的高阶数独。蒜头君做完发现没有正解,不知道对不对? 不知道聪明的你能否给出一个标准答案?

标准数独是由一个给与了提示数字的 9×9网格组成,我们只需将其空格填上数字,使得每一行,每一列以及每一个 3×3 宫都没有重复的数字出现。



输出这个数独得正解,输出格式如下:

2 6 * * * * * *

5 * 2 * * 4

1 * * * * 7

3 * * 2 * 1 8 *

3 * 9 * * *

5 4 * 1 * * 7 *

5 * * * * 1 * * *

6 * * 9 * 7 * * *

7 5 *

把上面的 * 替换成 1−91 - 91−9 就可以了

提醒:两个数字之间要有一个空格,其他地方不要输出多余的符号。

本题答案不唯一,符合要求的答案均正确

/*
*26******
***5*2**4
***1****7
*3**2*18*
***3*9***
*54*1**7*
5****1***
6**9*7***
******75*
*/
#include<iostream>
#include<cstdio>
using namespace std;
int maze[9][9];
void dfs(int pos);
int flag = 0;
int judge(int x,int y ,int m);
int main()
{
char ch;
for(int i = 0;i<9;i++)
{
for(int j = 0;j<9;j++)
{
scanf("%c",&ch);
if(ch!='*')
maze[i][j] = ch-'0';
else if(ch == '*') maze[i][j] = 0;
}
getchar();
}
//  for(int  i = 0;i<9;i++)
//      {
//          for(int j = 0;j<9;j++)
//          {
//              cout<<maze[i][j]<<' ';
//          }
//          cout<<endl;
//      }

dfs(1);
return 0;
}
void dfs(int pos)
{
if(flag == 1)return ;//flag的作用是表示找到一个答案即可 就停止递归
if(pos >81)
{
flag = 1;
for(int  i = 0;i<9;i++)
{
for(int j = 0;j<9;j++)
{
cout<<maze[i][j]<<' ';
}
cout<<endl;
}
return ;
}
//将pos转化成x
aed2
y坐标
int x = (pos-1)/9;//当pos == 9 减一再除9还是0
int y = pos%9-1;
if(y==-1) y = 8;//在最后一列

if(maze[x][y] == 0)
{
for(int i = 1;i<=9;i++)
{
if(judge(x,y,i) == 1)
{
maze[x][y] = i;
dfs(pos+1);
maze[x][y] = 0;
}
}
}
else dfs(pos+1);

}
int judge(int x,int y,int m)
{
for(int i = 0;i<9;i++)
{
if(maze[x][i] == m)
return 0;
}
for(int i = 0;i<9;i++)
{
if(maze[i][y] == m)
return 0;
}
for(int i = x / 3 * 3;i < x / 3 * 3 + 3;++i){
for(int j = y / 3 * 3;j < y / 3 * 3 + 3;++j){
if(maze[i][j] == m){
return 0;
}
}
}
return 1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: