Noip模拟题解题报告

Pro

题目链接

Sco

预计得分: 100 + 70 + 80 = 250

实际得分: 90 + 70 + 80 = 240

没有 S P J T 3 评测得 50 ,手测数据得 80

Sol

enc

第一题说实话真的好水,就是一个很简单的字符串模拟题

按照题目中的做,就可以得到 90 分,(至少我第一次打了 90 分)

最后一种情况就是:如果 25 个字母都一一对应确定,那么剩下的字母一定对应确定

其实打程序的时候想到这一点了,然而脑子一热,认为输入 25 个字母了……

只需要判断是否已经有 25 个不相同的字母被确定,然后特殊处理出最后的字母,强制确定

剩下的一一对应就好。

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

int num1[30] , num2[30] , ans[1005] , len1 , len2 , len3 , flag1 , flag2;
string s[4];

int main() {
    freopen("enc.in","r",stdin);
    freopen("enc.out","w",stdout);
    for(int i=1; i<=3; i++)
        cin>>s[i];
    len1 = s[1].length() , len2 = s[2].length() , len3 = s[3].length();
    if(len1 != len2) {
        printf("ERROR");
        return 0;
    }
    for(int i=0; i<len1; i++) {
        int id1 = s[1][i] - 'a' + 1;
        if(num1[id1]) {
            int id2 = s[2][i] - 'a' + 1;
            if(num1[id1] != id2) {
                printf("ERROR");
                return 0;
            }
        } else {
            int id2 = s[2][i] - 'a' + 1;
            if(num2[id2]) {
                printf("ERROR");
                return 0;
            } else {
                num1[id1] = id2;
                num2[id2] = id1;
            }
        }
    }
    for(int i=1; i<=26; i++) {
        if(num1[i])
            flag1++;
        if(num2[i])
            flag2++;
    }   
    if(flag1 == 25 && flag2 == 25) {
        int flag = 0;
        for(int i=1; i<=26; i++) {
            if(!num1[i])
                for(int j=1; j<=26; j++)
                    if(!num2[j]) {
                        num1[i] = j;
                        num2[j] = i;
                        flag = 1;
                        break;
                    }
            if(flag)
                break;
        }
    }
    for(int i=0; i<len3; i++) {
        int id1 = s[3][i] - 'a' + 1;
        if(!num2[id1]) {
            printf("ERROR");
            return 0;
        } else
            ans[i+1] = num2[id1];
    }
    for(int i=0; i<len3; i++)
        printf("%c",ans[i+1]+'a'-1);
    return 0;
}

sort

其实对随便一组数据(样例)简单分析一下,就可以发现本题就是一个裸的 L I S

怎么分析知道考的是LIS呢?其实我们可以把最后的满足条件的想象为放在一个集合内

那么一定要让集合内元素都没有冲突才行

对于这组数据:1 4 2 3

我们可以发现 4 和 2 、3都有冲突

那么4 或者 (2 和 3) 与 1 在集合内(逻辑用语)

显然1 2 3 在一个集合内答案更大

但是我们考虑来自于答案的所有组合: 1 4 或 1 2 3 很容易发现是上升子序列

所以本题可以转化为: L I S 问题。

看数据范围, O ( n 2 ) 暴力可过 70 分, O ( n l o g n ) 可过 100 分。

100 分算法:贪心+二分 或 d p +线段树 或 b a l a b a l a ……

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

int n , num[100005] , low[100005] , ans;
inline int mymax(int a , int b) { return a>b?a:b; }

int main() {
    freopen("sort.in","r",stdin);
    freopen("sort.out","w",stdout);
    memset(low , 0x3f , sizeof(low));
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&num[i]);
    low[1] = num[1];
    for(int i=2; i<=n; i++) {
        int opt = lower_bound(low+1 , low+n+1 , num[i]) - low;
        low[opt] = num[i];
        ans = mymax(ans , opt);
    }
    printf("%d",ans);
    return 0;
}

game

S P J !!!

只打了个 O ( n 3 ) 的暴力,如果 S P J 可以的话,可得 80

100 分待更…… (楼下为 80 分代码)

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

int n , map[1005][1005];

int main() {
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    scanf("%d",&n);
    for(int i=1; i<=n; i++) {
        string s;
        cin>>s;
        for(int j=0; j<s.length(); j++)
            map[i][j+1] = s[j] - 48;
    }
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++) {
            if(map[i][j] && i!=j) {
                for(int k=1; k<=n; k++) {
                    if(map[j][k] && k!=i && j!=k) {
                        if(map[k][i]) {
                            printf("%d %d %d",i , j , k);
                            return 0;
                        }
                    }
                }
            }
        }
    printf("-1");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43061009/article/details/82558114