zoukankan      html  css  js  c++  java
  • 一次更愚蠢的NOIP模拟赛

    都可以从COGS上找到

    纵横字谜krizaljka

    时间限制: 1 Sec  内存限制: 32 MB

    题目描述

    给出两个单词,找到第一个相同的字母,然后第一个单词横数输出,第二个竖着输出形成十字形。

    如果两个单词有多个位置的字母相同,则先考虑在第一个单词中位置靠前的相同字母。

    例如,第一个单词是 “ABBA”,第二个单词是 “CCBB",形成的纵横字谜格式为:

    .C..
    .C..
    ABBA
    .B..

    输入

    1行:2个空格分开的单词AB,长度均不超过30个字符。

    输出

    A长度为MB长度为N,则输出共M行,每行N个字符。A单词橫着输出,B单词竖着输出。不是单词字母的位置填充句点'.'

    样例输入

    REPUBLIKA HRVATSKA

    样例输出

    H........

    REPUBLIKA

    V........

    A........

    T........

    S........

    K........

    A........

    Solution

    考点:是否会编程

    随便枚举,然后随便输出

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    void Freopen() {freopen("krizaljka.in","r",stdin); freopen("krizaljka.out","w",stdout);}
    void Fclose() {fclose(stdin); fclose(stdout);}
    char s1[40],s2[40];
    char S[40][40];
    int main()
    {
        Freopen();
        scanf("%s",s1+1),scanf("%s",s2+1);
        int ls1=strlen(s1+1),ls2=strlen(s2+1);
        int p1=0,p2=0;
        for (int i=1; i<=ls1; i++)
            for (int j=1; j<=ls2; j++)
                if (s2[j]==s1[i] && !p1 && !p2) {p1=i,p2=j;}
        for (int i=1; i<=ls2; i++)
            for (int j=1; j<=ls1; j++)
                S[i][j]='.';
        for (int i=1; i<=ls1; i++)
            S[p2][i]=s1[i];
        for (int j=1; j<=ls2; j++)
            S[j][p1]=s2[j];
        for (int i=1; i<=ls2; i++)
            {
                for (int j=1; j<=ls1; j++)
                    putchar(S[i][j]);
                if (i!=ls2) puts("");
            }
        Fclose();
        return 0;
    }
    毫无意义的代码


    砍树eko

    时间限制: 1 Sec  内存限制: 32 MB

    题目描述

    N棵树,每棵都有一个整数高度。有一个木头的总需要量M

    现在确定一个最大的统一的砍树高度H,如果某棵树的高度大于H,则高出的部分被砍下。使得所有被砍下的木材长度之和达到M(允许稍超过M)。

    例如,有4棵树,高度分别是20 15 10 17, 需要的木材长度为 7,砍树高度为15时,第1棵树被砍下5,第4棵树被砍下2,得到的总长度为7。如果砍树高度为16时,第1棵树被砍下4,第4棵树被砍下1,则得到的木材数量为5

    输入

    1行:2个整数NMN表示树木的数量(1 ≤ N ≤ 1 000 000)M表示需要的木材总长度(1 ≤ M ≤ 2 000 000 000)

    2行: N个整数表示每棵树的高度,值均不超过1  000  000  000。所有木材高度之和大于M,因此必然有解。

    输出

    1行:1个整数,表示砍树的最高高度。

    样例输入

    5 20

    4 42 40 26 46

    样例输出

    36

    Solution

    二分+判断   随便写....

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    void Freopen() {freopen("eko.in","r",stdin); freopen("eko.out","w",stdout);}
    void Fclose() {fclose(stdin); fclose(stdout);}
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 1000010
    int N,M,h[MAXN],maxh;
    bool check(int x)
    {
        long long sum=0;
        for (int i=1; i<=N; i++)
            if (h[i]>x) sum+=h[i]-x;
        return sum>=M;
    }
    int main()
    {
        Freopen();
        N=read(),M=read();
        for (int i=1; i<=N; i++) h[i]=read(),maxh=max(maxh,h[i]);
        int l=1,r=maxh;
        while (l<=r)
            {
                int mid=(l+r)>>1;
                if (check(mid)) l=mid+1; else r=mid-1;
            }
        printf("%d
    ",l-1);
        Fclose();
        return 0;
    }
    又是一个毫无意义的代码


    DNA

    时间限制: 1 Sec  内存限制: 32 MB

    题目描述

    给出1个只有AB组成的长度为N的字符串,现在给出两种变换方式:第一种是翻转一个字母,A变成B,或B变成A;第二种是翻转字符串某个字符的前缀(包括该字符),将前缀中所有的A变成B,或者所有的B变成A

    现在要把给出的字符串变成全A,问至少需要多少次变换操作。

    输入

    1: 一个正整数N1<=N<=1000000,表示字符串的长度。
    2: N个字符,要么是A,要么是B,表示初始字符串.

    输出

    1行:一个整数,表示最少需要的翻转次数

    样例输入

    12

    AAABBBAAABBB

    样例输出

    4

    Solution

    贪心或者DP

    从最后一个位置开始从前往后扫,

    如果遇见一个单个的'B'则单独修改ans++,如果遇见>=2个‘B'则前缀翻转ans++

    翻转随便打个标记

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    void Freopen() {freopen("dna.in","r",stdin); freopen("dna.out","w",stdout);}
    void Fclose() {fclose(stdin); fclose(stdout);}
    #define MAXN 1000100
    int N,s[MAXN],ans;
    char S[MAXN];
    int main()
    {
        Freopen();
        scanf("%d",&N);
        scanf("%s",S+1);
        for (int i=1; i<=N; i++) if (S[i]=='A') s[i]=1; else s[i]=0;
        int i=N,f=0;
        while (i>=1)
            {
                if ((f==0 && s[i]==1) || (f==1 && s[i]==0)) {i--; continue;}
                if ((f==0 && s[i]==0 && s[i-1]!=0) || (f==1 && s[i]==1 && s[i-1]!=1)) {ans++; i--; continue;}
                if ((f==0 && s[i]==0 && s[i-1]==0) || (f==1 && s[i]==1 && s[i-1]==1))
                    {
                        int j;
                        for (j=i; j>=1; j--) if ((f==0 && s[i]==0) || (f==1 && s[i]==1)) {ans++; f^=1; i=j; break;}
                        continue;
                    }
            }
        printf("%d
    ",ans);
        Fclose();
        return 0;
    }
    丑陋的代码


    旅行

    POD

    现在让我们来对一个交通运输图进行研究,这可能是一个公交车的线路网、有轨电车线路网、地下铁的线路网或是其他的一个什么。这个图中的顶点(从1n标号)为车站,边(pi ,pj)(这里pi ¹ pj)表示在顶点pi和顶点pj间存在一条直接连接两点的路(1 £ pi, pj £ n)。在图中有从1k编号的k条运输路线,第l号路线是用一个车站序列pl,1, pl,2, …, pl,sl来描述的,它们为使用这个线路的车辆将依次经过的车站。并且我们给出它们之间的距离rl,1, rl,2, …, rl,sl-1,其中rl,i表示从车站pl,i到车站pl,i+1所需的时间。对于一条线路来说,它上面所有的车站都是不相同的(也就是说,若i ¹ j,则pl,i ¹ pl,j)。且线路l将以频率cl运行。这里cl为集合{6, 10, 12, 15, 20, 30 ,60}中的一个数,它表示每个小时的0, cl, 2cl, …, 60分钟的时候在路线l上的将有两辆车同时从车站pl,1pl,sl出发相对着行进。

    在这样一个运输网络中,我们想从其中的一个车站x出发用尽可能少的时间到达车站y。这里我们假设最少的时间不会超过24个小时,且在中途换车的时候的时间不计。

    示例:

    在下图中你可以看到一个具有六个车站和两条路线的运输网络。路线一上的车站序列为1346,路线二上的车站序列为2435,且两条路线的频率分别为c1=15c2=20。车辆在各车站间移动时的耗费都分别用12的下标标在了图上。

     

    现在我们假设在23点30分的时候我们在车站5想要到车站6去。我们必须等上10分钟才可以搭上一辆路线2的车离开。然后我们就面临着两种选择:一种是在2351分到车站3等上3分钟并改乘路线1的车于016分到达车站6;另一种是在08分到达车站4等上13分钟再换路线1的车于031分到达车站6。显然最早我们能在016分到达车站6

    任务:

    请写一个程序:

    从文本文件POD.IN中读入对该交通运输网的描述、起点和终点、还有出发的时间;

    找出从起点到终点的最少时间;

    把最找到达终点的时间输出到文本文件POD.OUT中。

    输入格式:

    在文本文件POD.IN的第一行包括六个用空格分开的整数,分别为:

    l n1 £ n £ 1000,为车站的数目;

    l k1 £ k £ 2000,为路线的数目;

    l x1 £ x £ n,为起点的车站编号;

    l y1 £ y £ n,为终点的车站编号;

    l gx0 £ gx £ 23,为出发时间的小时数;

    l mx0 £ mx £ 59,为出发时间的分钟数。

    车站是从1n编号的,运输路线是用1k编号的。以下的3k行为对运输路线的描述。这些行中每3行构成一个对一条路线的描述,第k个三行的意义如下:

    第一行包括两个用空格分开的整数,sl2 £ sl£ n)为该路线上车站的数目,还有cl{6, 10, 12, 15, 20, 30, 60}中的一个元素),为该路线运行的频率;

    第二行包括sl个用空格分开的不同的整数,为pl,1, pl,2, …,pl,sl1£ pl,i£ n),即该路线上的车站;

    第三行包括sl-1个整数rl,1, rl,2, …,rl,sl-1为在路线上相邻两个车站间移动所需的时间(1£ rl,i£ 240)。

    在所有的运输路线上的总车站数不超过4000(也就是说s1 + s2 + … + sk £ 4000)。

    输出格式:

    你的程序应该在文本文件POD.OUT中输出两个整数gy0£ gy£ 23)和my0£ my£ 59),表示到达y点时的小时数和分钟数。

    样例:

    输入(POD.IN):

    6 2 5 6 23 30

    4 15

    1 3 4 6

    9 12 10

    4 20

    5 3 4 2

    11 17 11

    输出(POD.OUT):

    0 16

    Solution

    这个题还有点说的....

    两个限制的最短路,首先可以证明最优性,早到一个点,一定不会比晚到要差

    所以我们就可以转化成最短路了

    正常的连边,边权记为时间,但是每条边额外记录两个东西(这条路径的频率c,和从这条路径的发车点到这条边需要经过的时间ct)

    然后正常的Dijkstra的比较是dis+edge[i].v<dis[edge[i].to进行更新和放入堆中,这里只需要多计算一下等待的时间

    有当前的时间,发车的频率,以及车到这个点的时间,就可计算出最快坐上车的时间(最短等待时间)

    然后裸上最短路,算出到达终点的最短分钟,然后就可得到答案了

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    void Freopen() {freopen("pod.in","r",stdin); freopen("pod.out","w",stdout);}
    void Fclose() {fclose(stdin); fclose(stdout);}
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int N,K,S,T,Gx,Mx;
    struct EdgeNode{int next,to,t,c,ct,from;}edge[4000<<1];
    int head[1010],cnt=1;
    void AddEdge(int u,int v,int w,int c,int ct) 
    {
        cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].t=w;
        edge[cnt].c=c; edge[cnt].ct=ct; edge[cnt].from=u;
    }//c表示频率,ct表示开始时到这个点的时间和,t表示经过这条边的时间 
    struct CaseNode {int num,c; int R[1001],t[1001],st1[1001],st2[1001]; }cas[2001];
    #define Pa pair<int,int>
    priority_queue<Pa,vector<Pa> , greater<Pa> >q;
    int dis[1010];
    #define INF 0x7fffffff
    void Dijkstra()
    {
        for (int i=1; i<=N; i++) dis[i]=INF;
        q.push( make_pair(0,S) ); dis[S]=0;
        int at;
        while (!q.empty())
            {
                int now=q.top().second;
                int Dis=q.top().first;
                q.pop();
                for (int i=head[now]; i; i=edge[i].next)
                    {
                        int tmpt=(Dis+Mx-edge[i].ct); while (tmpt<=0) tmpt+=60; tmpt%=60;
                        at=0;
                        if (tmpt%edge[i].c==0) at=Dis; else {int tt=tmpt/edge[i].c; int cz=(tt+1)*edge[i].c-tmpt; at=Dis+cz;} 
                        if (at + edge[i].t < dis[edge[i].to])
                            dis[edge[i].to]=at + edge[i].t,q.push(make_pair(dis[edge[i].to],edge[i].to));
                    }
            }
    }
    int main()
    {
        Freopen();
        N=read(),K=read(),S=read(),T=read(),Gx=read(),Mx=read();
        for (int i=1; i<=K; i++)
            {
                cas[i].num=read(),cas[i].c=read();
                for (int j=1; j<=cas[i].num; j++) cas[i].R[j]=read();
                for (int j=1; j<=cas[i].num-1; j++) cas[i].t[j]=read(),cas[i].st1[j]=cas[i].st1[j-1]+cas[i].t[j];
                for (int j=1; j<=cas[i].num-1; j++) AddEdge(cas[i].R[j],cas[i].R[j+1],cas[i].t[j],cas[i].c,cas[i].st1[j-1]);
                for (int j=cas[i].num-1; j>=1; j--) cas[i].st2[j]=cas[i].st2[j+1]+cas[i].t[j];
                for (int j=cas[i].num; j>=2; j--) AddEdge(cas[i].R[j],cas[i].R[j-1],cas[i].t[j-1],cas[i].c,cas[i].st2[j]); 
            }
    //    for (int i=2; i<=cnt; i++) printf("%d--->%d %d %d %d
    ",edge[i].from,edge[i].to,edge[i].t,edge[i].c,edge[i].ct);
        Dijkstra();
    //    for (int i=1; i<=N; i++) printf("%d ",dis[i]); puts("");
        int Gt=(dis[T]+Mx)/60,Mt=dis[T];
        printf("%d %d
    ",(Gt+Gx)%24,(Mt+Mx)%60);
        Fclose();
        return 0;
    }
    Code


    启发:

    think twice ,code once

    要对拍!!T4就因为最后+=XXX写成了++然后就交了,结果炸成20,本来能AK的...

    细节地方要反复推敲!

  • 相关阅读:
    Best Time to Buy and Sell Stock(动态规划)
    word break
    Container With Most Water
    Partition List(链表的插入和删除操作,找前驱节点)
    取样问题(编程珠玑)
    统计指标
    脚本化加载文件与转储
    azkaban调度
    hive自定义UDTF函数叉分函数
    hive数据仓库建设
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5795997.html
Copyright © 2011-2022 走看看