计蒜客2018蓝桥杯省赛B组模拟赛(一)D,E,F题

4. (11')LIS

        LIS是最长上升子序列。什么是最长上升子序列? 就是给你一个序列,请你在其中求出一段最长严格上升的部分,它不一定要连续。
        就像这样:2, 3, 4, 7 和 2, 3, 4, 6 就是序列 2 5 3 4 1 7 6 的两个上升子序列,最长的长度是 4。

解析:最长上升子序列问题:dp[i] = max(dp[i], d[j]+1);

具体代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int f[10000], b[10000];
int max(int a, int b) {
    return a > b ? a : b;
}
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);
            }
        }
        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;
}

正确答案:f[i] = max(f[i], f[j]+1);

5. (13')全排列

        相信大家都知道什么是全排列,但是今天的全排列比你想象中的难一点。我们要找的是全排列中,排列结果互不相同的个数。

        比如:aab 的全排列就只有三种,那就是aab,baa,aba。

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

解析:如果全排列互不相同,只需将字符串重复的字符排列一次即可,手动排列一遍aab,就知道了,比如初始字符顺序是123,那么会出现213,这种情况,两者都是aab,可是重复了,所以只需要,避免此类的重复即可。

具体代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 1000

char str[N], buf[N];
int vis[N], total, len;//212  122

void arrange(int num) {
    int i, j;
    if (num == len) {
        printf("%s\n", buf);
        total++;
        return;
    }
	for (i = 0; i < len; ++i) {
        if (!vis[i]) {
            for (j = i + 1; j < len; ++j) {
                if (vis[j] && str[i] == str[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);
        int i, j;
        for (i = 0; i < len; ++i) {
            for (j = i + 1; j < len; ++j) {
                if (str[i] > str[j]) {
                    char tmp = str[i];
                    str[i] = str[j];
                    str[j] = tmp;
                }
            }
        }
        total = 0;
        buf[len] = '\0';
        arrange(0);
        printf("Total %d\n", total);
    }
    return 0;
}

正确答案:vis[j] && str[i] == str[j]

6. (16')数独

       蒜头君今天突然开始怀念童年了,想回忆回忆童年。他记得自己小时候,有一个很火的游戏叫做数独。便开始来了一局紧张而又刺激的高阶数独。蒜头君做完发现没有正解,不知道对不对? 不知道聪明的你能否给出一个标准答案?
       标准数独是由一个给与了提示数字的 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 - 9 就可以了
提醒:两个数字之间要有一个空格,其他地方不要输出多余的符号。

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

解析:这是一个数独问题,递归剪纸也是很快的。求数独链接:点击打开链接

正确答案:

#include <stdio.h>
int main() {
    printf("%s\n", "1 2 6 7 3 4 5 9 8" );
    printf("%s\n", "3 7 8 5 9 2 6 1 4" );
    printf("%s\n", "4 9 5 1 6 8 2 3 7" );
    printf("%s\n", "7 3 9 4 2 5 1 8 6" );
    printf("%s\n", "8 6 1 3 7 9 4 2 5" );
    printf("%s\n", "2 5 4 8 1 6 3 7 9" );
    printf("%s\n", "5 4 7 2 8 1 9 6 3" );
    printf("%s\n", "6 1 3 9 5 7 8 4 2" );
    printf("%s\n", "9 8 2 6 4 3 7 5 1" );
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值