一次更愚蠢的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的...

细节地方要反复推敲!

原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5795997.html