• 9.22 noip模拟试题


    水灾(sliker.cpp/c/pas) 1000MS  64MB

    大雨应经下了几天雨,却还是没有停的样子。土豪CCY刚从外地赚完1e元回来,知道不久除了自己别墅,其他的地方都将会被洪水淹没。

    CCY所在的城市可以用一个N*M(N,M<=50)的地图表示,地图上有五种符号:“. * X D S”。其中“X”表示石头,水和人都不能从上面经过。“.”表示平原,CCY和洪水都可以经过。“*”表示洪水开始地方(可能有多个地方开始发生洪水)。“D”表示CCY的别墅。“S”表示CCY现在的位置。

    CCY每分钟可以向相邻位置移动,而洪水将会在CCY移动之后把相邻的没有的土地淹没(从已淹没的土地)。

    求CCY回到别墅的最少时间。如果聪哥回不了家,就很可能会被淹死,那么他就要膜拜黄金大神涨RP来呼叫直升飞机,所以输出“ORZ hzwer!!!”。

    输入文件 sliker.in

    输出文件 sliker.out

    Input

    3 3

    D.*

    .S.

     

    Output

    3

     

    Input

    3 3

    D.*

    ..S

     

    Output

    ORZ hzwer!!!

     

    Input

    3 6

    D…*.

    .X.X..

    ….S.

     

    Output

    6

      裸bfs不贴了(其实是因为第一次写完之后发生了一个悲惨的故事~~ 没存电脑就XX了)

     

     

    某种数列问题  (jx.cpp/c/pas) 1000MS 256MB

     

    众所周知,chenzeyu97有无数的妹子(阿掉!>_<),而且他还有很多恶趣味的问题,继上次纠结于一排妹子的排法以后,今天他有非(chi)常(bao)认(cheng)真(zhe)去研究一个奇怪的问题。有一堆他的妹子站成一排,然后对于每个妹子有一个美丽度,当然美丽度越大越好,chenzeyu97妹子很多,但是质量上不容乐观,经常出现很多美丽度为负数的妹子(喜闻乐见),chenzeyu97希望从一排妹子里找出3队连续的妹子,使她们的美丽度和最大。注意,一个妹子不能被编入多个队伍而且一定要拿出三队,不然czy会闲着没事做~。

    简单滴说就是:

    给定一个数列,从中找到3个无交集的连续子数列使其和最大。

    【输入文件】

    第一行一个数n,表示数列长度。

    接下来有n行,每行一个数,第i行为第i个数。

     

    【输出文件】

    仅有一个数,表示最大和。

     

    【样例输入】 jx.in

    10

    -1

    2

    3

    -4

    0

    1

    -6

    -1

    1

    -2

     

    【样例输出】 jx.out

    7

     

    【样例说明】

    第一队妹子取2,3。

    第二队妹子取0,1。

    第三队妹子取1。

     

    【数据范围】

    请大家放心,虽然chenzeyu97妹子无数,但是这次他叫来的个数n是有限的。=v=

    对于30%的数据,妹子数不大于200。

    对于60%的数据,妹子数不大于2000。

    对于100%的数据,妹子数1000000。

    而且,由于chenzeyu97没有CCR那样的影响力,所以他的妹子选完的最大美丽度和不超过maxlongint。(注:CCR随便选就爆long long,因为他是把妹狂魔=V=)。

     

     开始想的是跑7次最大连续子段和 后来发现由bug 而且不好修复 目测能蒙对一部分数据吧

    正解dp

    /*以后养成好习惯 写暴力对拍(可我老是写错暴力...)*/
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,a[110],ans=-inf;
    void Dfs(int now,int num,int s){
        if(now==n+1){
            if(num==4)ans=max(ans,s);
            return;
        }
        Dfs(now+1,num,s);
        Dfs(now+1,num,s+a[now]);
        Dfs(now+1,num+1,s+a[now]);
        Dfs(now+1,num+1,s);
    }
    int main()
    {
        freopen("jx.in","r",stdin);
        freopen("jx.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        Dfs(1,1,0);
        printf("%d
    ",ans);
        return 0;
    }
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 1000010
    using namespace std;
    int n,a[maxn],f[maxn][4][2];
    int main()
    {
        freopen("jx.in","r",stdin);
        freopen("jx.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        memset(f,-127/3,sizeof(f));
        f[0][0][0]=0;
        for(int i=1;i<=n;i++)
            for(int j=0;j<=3;j++){
                f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1]);
                if(j)f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1])+a[i];
                f[i][j][1]=max(f[i][j][1],f[i-1][j][1]+a[i]);
            }
        printf("%d
    ",max(f[n][3][0],f[n][3][1]));
    }
    View Code

    密码锁 1000MS 512MB

    Input: password.in

    Output: password.out

    【题目描述】

    hzwer有一把密码锁,由N个开关组成。一开始的时候,所有开关都是关上的。当且仅当开关x1,x2,x3,...xk为开,其他开关为关时,密码锁才会打开。

    他可以进行M种的操作,每种操作有一个size[i],表示,假如他选择了第i种的操作的话,他可以任意选择连续的size[i]个格子,把它们全部取反。(注意,由于黄金大神非常的神,所以操作次数可以无限>_<)

    本来这是一个无关紧要的问题,但是,黄金大神不小心他的钱丢进去了,没有的钱他哪里能逃过被chenzeyu97 NTR的命运?>_<  于是,他为了虐爆czy,也为了去泡更多的妹子,决定打开这把锁。但是他那么神的人根本不屑这种”水题”。于是,他找到了你。

    你的任务很简单,求出最少需要多少步才能打开密码锁,或者如果无解的话,请输出-1。

    【输入格式】

    第1行,三个正整数N,K,M,如题目所述。

    第2行,K个正整数,表示开关x1,x2,x3..xk必须为开,保证x两两不同。

    第三行,M个正整数,表示size[i],size[]可能有重复元素。

    【输出格式】

    输出答案,无解输出-1。

    【样例输入1】

    10 8 2

    1 2 3 5 6 7 8 9

    3 5

    【样例输出1】

    2

    【样例输入2】

    3 2 1

    1 2

    3

    【样例输出2】

    -1

     

     

    【数据规模】

    对于50%的数据,1≤N≤20,1≤k≤5,1≤m≤3;

    对于另外20%的数据,1≤N≤10000,1≤k≤5,1≤m≤30;

    对于100%的数据,1≤N≤10000,1≤k≤10,1≤m≤100。

     机智的题解

    /*
    完全没思路的 我是蒟蒻QAQ
    看了题解 好巧妙Qrz
    对于区间取反 复杂度是O(n)
    但是因为这题序列只有01
    如果操作查分序列的话就快多了
    先搞出查分序列 然后bfs求出每两个点的1相互抵消最少操作次数
    因为最后的序列最多20个1 所以状丫dp搞一搞求出min操作次数
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define maxn 10010
    using namespace std;
    int n,m,k,size[110],a[maxn],c[maxn],s[maxn],cnt,step[110][110];
    int f[maxn],dis[maxn],dp[1<<22],inf;
    struct node{
        int x,t;
    };
    queue<node>q;
    void Bfs(int S,int o){
        while(!q.empty())q.pop();
        memset(f,0,sizeof(f));
        memset(dis,127/3,sizeof(dis));
        inf=dis[0];
        q.push((node){S,0});f[S]=1;dis[S]=0;
        while(!q.empty()){
            node p=q.front();q.pop();
            for(int i=1;i<=k;i++){
                int y=p.x+size[i];
                if(y<=n&&f[y]==0){
                    f[y]=1;dis[y]=p.t+1;
                    q.push((node){y,dis[y]});
                }
                y=p.x-size[i];
                if(y>=1&&f[y]==0){
                    f[y]=1;dis[y]=p.t+1;
                    q.push((node){y,dis[y]});
                }
            }
        }
        for(int i=1;i<=cnt;i++)
            if(dis[c[i]]<inf)step[o][i]=dis[c[i]];
            else step[o][i]=inf;
    }
    int main()
    {
        freopen("password.in","r",stdin);
        freopen("password.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++){
            int x;scanf("%d",&x);a[x]++;
        }
        for(int i=1;i<=k;i++)
            scanf("%d",&size[i]);
        n++;
        for(int i=1;i<=n;i++)
            s[i]=a[i]-a[i-1];
        for(int i=1;i<=n;i++)
            if(s[i])c[++cnt]=i;
        for(int i=1;i<=cnt;i++)
            Bfs(c[i],i);
        memset(dp,127/3,sizeof(dp));
        inf=dp[0];dp[0]=0;
        for(int i=0;i<=(1<<cnt)-1;i++){
            int j;
            for(int k=1;k<=cnt;k++)
                if((1<<k-1)&i){j=k;break;}
            for(int k=1;k<=cnt;k++)
                if((1<<k-1)&i)dp[i]=min(dp[i],dp[i^(1<<j-1)^
    
    (1<<k-1)]+step[j][k]);
        }
        if(dp[(1<<cnt)-1]==inf)printf("-1
    ");
        else printf("%d
    ",dp[(1<<cnt)-1]);
        return 0;
    }
    View Code

     conclusion

    /*
    今天发生了很凄惨的事情
    蛋疼捡了个优盘插了插
    然后电脑就嗝屁了 我的题
    导致很不爽没有在打T1 T2
    T1很水 bfs
    T2不是正解 乱搞似乎60分来好像
    T3不会正解暴力
    最后看了正解觉得好机智Orz
    区间修改很慢 简化成查分序列单点修改
    还有一问题就是题目规定了每个区间长度
    然后bfs出查分序列中改每两个的步数
    然后根据k<=10 状丫dp跑一下
    很厉害的题解Orz
    
    还是重点看T2 T3这样的我也不指望考场上写出来 
    成败在T2 然而今天并没有想出正解
    开始就进了Lis的死胡同 然后各种乱搞....
    正解dp 一维位数 一维选了几个 一维维护这个选没选
    可以的 想到dp剩下的就不是太难了 
    关键是一开始没有想对算法 方向不对
    最后发现错误也已经是没时间重新开始了 
    */
    View Code

     

  • 相关阅读:
    Android环境的构建
    [转载]java代码采用哈夫曼实现压缩软件
    [转载]java代码采用哈夫曼实现压缩软件
    用JAVA实现字符串压缩算法
    用JAVA实现字符串压缩算法
    J2ME 图片压缩算法
    J2ME 图片压缩算法
    C# 操作Excel
    csharp excel interop programming
    Sharepoint tools
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5896932.html
Copyright © 2020-2023  润新知