7.3模拟比赛

067.3  NOIP模拟赛

说明:本次考试3道题3个小时。

1、洛谷P1003 铺地毯==codevs1134 铺地毯

题目描述

为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n 张地毯,编号从 1 到n 。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。

地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。

输入输出格式

输入格式:

输入文件名为carpet.in 。

输入共n+2 行。

第一行,一个整数n ,表示总共有 n 张地毯。

接下来的n 行中,第 i+1 行表示编号i 的地毯的信息,包含四个正整数 a ,b ,g ,k ,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a ,b )以及地毯在x轴和y 轴方向的长度。

第n+2 行包含两个正整数 x 和y,表示所求的地面的点的坐标(x ,y)。

输出格式:

输出文件名为carpet.out 。

输出共1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1 。

输入输出样例

输入样例#1:

【输入样例1】
3
1 0 2 3
0 2 3 3
2 1 3 3
2 2
【输入样例2】
3
1 0 2 3
0 2 3 3
2 1 3 3
4 5

输出样例#1:

【输出样例1】
3
【输出样例2】
-1

说明

【样例解释1】

如下图,1 号地毯用实线表示,2 号地毯用虚线表示,3 号用双实线表示,覆盖点(2,2)的最上面一张地毯是 3 号地毯。

【数据范围】

对于30% 的数据,有 n ≤2 ;

对于50% 的数据,0 ≤a, b, g, k≤100;

对于100%的数据,有 0 ≤n ≤10,000 ,0≤a, b, g, k ≤100,000。

noip2011提高组day1第1题

太水了,不解释

AC代码:

#include<iostream>
using namespace std;
#define N 100100
int a[N],b[N],c[N],d[N],k=-1,n,x,y;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i]>>b[i]>>c[i]>>d[i];
    cin>>x>>y;
    for(int i=1;i<=n;i++)
        if(x-a[i]>=0&&x-a[i]<=c[i]&&y-b[i]>=0&&y-b[i]<=d[i])
            k=i;
    cout<<k<<endl;
    return 0;
}

 

2、洛谷P1079 Vigenère 密码==codevs1197 Vigenère密码

题目描述

16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密

码。Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为

南军所广泛使用。

在密码学中,我们称需要加密的信息为明文,用 M 表示;称加密后的信息为密文,用

C 表示;而密钥是一种参数,是将明文转换为密文或将密文转换为明文的算法中输入的数据,

记为 k。 在 Vigenère 密码中,密钥 k 是一个字母串,k=k1k2…kn。当明文 M=m1m2…mn时,

得到的密文 C=c1c2…cn,其中 ci=mi®ki,运算®的规则如下表所示:

Vigenère 加密在操作时需要注意:

  1. ®运算忽略参与运算的字母的大小写,并保持字母在明文 M 中的大小写形式;
  2. 当明文 M 的长度大于密钥 k 的长度时,将密钥 k 重复使用。

例如,明文 M=Helloworld,密钥 k=abc 时,密文 C=Hfnlpyosnd。

输入输出格式

输入格式:

输入共 2 行。

第一行为一个字符串,表示密钥 k,长度不超过 100,其中仅包含大小写字母。第二行

为一个字符串,表示经加密后的密文,长度不超过 1000,其中仅包含大小写字母。

输出格式:

输出共 1 行,一个字符串,表示输入密钥和密文所对应的明文。

输入输出样例

输入样例#1:

CompleteVictory
Yvqgpxaimmklongnzfwpvxmniytm 

输出样例#1:

Wherethereisawillthereisaway 

说明

【数据说明】

对于 100%的数据,输入的密钥的长度不超过 100,输入的密文的长度不超过 1000,且

都仅包含英文字母。

NOIP 2012 提高组 第一天 第一题

注意点这里,其余问题不大

AC代码:

#include<cstdio>
#include<cstring>
using namespace std;
#define N 1024
char key[N],a[N];
inline int dx(char c){//锁定原字母的大小写
    if(c>=‘A‘&&c<=‘Z‘)return 1;
    else if(c>=‘a‘&&c<=‘z‘)return 0;
}
inline char deal(char c,int i){//处理之后密文的大小写
    if(i==1&&c>=‘a‘&&c<=‘z‘)return c-32;
    else if(i==0&&c>=‘A‘&&c<=‘Z‘)return c+32;
    else return c;
}
void action(){
    int lena=strlen(a),lenk=strlen(key);
    char c1,c2,ans;
    for(int i=0;i<lena;i++){
        int flag=dx(a[i]);
        c1=deal(a[i],1);
        c2=deal(key[i%lenk],1);//密钥可能短
        int xx=c1-‘A‘-(c2-‘A‘);
        if(xx<0) xx+=26;//翻译
        ans=deal(xx+‘A‘,flag);
        printf("%c",ans);
    }
    puts("");
}
int main(){
    scanf("%s%s",key,a);
    action();
    return 0;
}

3、洛谷P1514 引水入城==codevs1066 引水入城

题目描述

在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠。该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度。

为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。

因此,只有与湖泊毗邻的第1 行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。由于第N 行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。

输入输出格式

输入格式:

输入文件的每行中两个数之间用一个空格隔开。输入的第一行是两个正整数N 和M,表示矩形的规模。接下来N 行,每行M 个正整数,依次代表每座城市的海拔高度。

输出格式:

输出有两行。如果能满足要求,输出的第一行是整数1,第二行是一个整数,代表最少建造几个蓄水厂;如果不能满足要求,输出的第一行是整数0,第二行是一个整数,代表有几座干旱区中的城市不可能建有水利设施。

输入输出样例

输入样例#1:

【输入样例1】
2 5
9 1 5 4 3
8 7 6 1 2

【输入样例2】
3 6
8 4 5 6 4 4
7 3 4 3 3 3
3 2 2 1 1 2

输出样例#1:

【输出样例1】
1
1

【输出样例2】
1
3

说明

【样例1 说明】

只需要在海拔为9 的那座城市中建造蓄水厂,即可满足要求。

【样例2 说明】

上图中,在3 个粗线框出的城市中建造蓄水厂,可以满足要求。以这3 个蓄水厂为源头

在干旱区中建造的输水站分别用3 种颜色标出。当然,建造方法可能不唯一。

【数据范围】

这个题有意思,着重讲一下。

闲扯一会儿:

考试的时候思路基本上和题解一样,就连dp方程都一样~~貌似以前看过。

考试的时候,想着bfs比dfs快,结果是bfs->TLE,dfs->AC.那分啊,心疼死我了,tyts。

解题思路:

对于第一行的每个城市,我们可以预处理出在这座城市建立蓄水厂,水流能到达最下面一行的哪些城市;如果最终的题目是有解的,那么最后一行这些被覆盖的城市是连续的,反证:如果水流到达最下面一行的城市是断开不连续的,则说明中间有城市海拔比四周都高,其他城市过来的水流也流不上去,因此永远无法被覆盖,与我们之前的条件相矛盾。

预处理出来每做城市的覆盖范围后,这道题就变成这样:给你长度为m的x轴,现在有m条线段,求覆盖x轴至少要多少根线段。

我们既可以用DP,也可以用贪心,这里采用DP

设,f[i]表示覆盖1~i所需要的最少线段g[j]表示线段i覆盖的区间

则 dp方程:f(i) = min{ f[i] , f[g[j].L - 1] + 1 |  i >= g[i].L&&i <= g[i].R }

考试代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 1010
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
int bo[N],vis[N],l[N],r[N],f[N];
struct node{
    int x,y,v;
}map[N][N];
int n,m;
int bfs(int s,int x,int y){
    queue<node>que;
    que.push(map[x][y]);
    while(!que.empty()){
        node h=que.front();que.pop();
        for(int i=0;i<4;i++){
            int xx=h.x+dx[i],yy=h.y+dy[i];
            if(h.v>map[xx][yy].v&&xx>0&&xx<=n&&yy>0&&yy<=m){
                que.push(map[xx][yy]);
                if(xx==n&&!vis[yy]){
                    vis[yy]=1,bo[yy]++;
                    if(yy<l[s]||!l[s]) l[s]=yy;
                    if(yy>r[s]) r[s]=yy;
                }
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&map[i][j].v);
            map[i][j].x=i;map[i][j].y=j;
        }
    }
    int sum=0,flag=0;
    for(int i=1;i<=m;i++){
        if(i>1&&map[1][i].v<map[1][i-1].v) continue;
        if(i<m&&map[1][i].v<map[1][i+1].v) continue;
        memset(vis,0,sizeof(vis));
        bfs(i,1,i);
    }
    for(int i=1;i<=m;i++){
        if(!bo[i]){
            flag=1;sum++;
        }
    }
    if(flag){printf("0\n%d\n",sum);return 0;}
    printf("1\n");
    for(int i=1;i<=m;i++){
        for(int j=l[i];j<=r[i];j++){
            if(f[j]>f[l[i]-1]+1||!f[j])
                f[j]=f[l[i]-1]+1;
        }
    }
    printf("%d\n",f[m]);
    return 0;
}

我看了各种题解,都说每个点(i,j)只能搜一遍(为什么只能搜一遍???),改完之后,依然WA,bfs搜不到?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 510
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
int bo[N],vis[N][N],l[N],r[N],f[N];
struct node{
    int x,y,v;
}map[N][N];
int n,m;
int bfs(int s,int x,int y){
    queue<node>que;
    que.push(map[x][y]);
    while(!que.empty()){
        node h=que.front();que.pop();
        for(int i=0;i<4;i++){
            int xx=h.x+dx[i],yy=h.y+dy[i];
            if(!vis[xx][yy]&&h.v>map[xx][yy].v&&xx>0&&xx<=n&&yy>0&&yy<=m){
                vis[xx][yy]=1;
                que.push(map[xx][yy]);
                if(xx==n){
                    bo[yy]++;
                    if(yy<l[s]||!l[s]) l[s]=yy;
                    if(yy>r[s]) r[s]=yy;
                }
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&map[i][j].v);
            map[i][j].x=i;map[i][j].y=j;
        }
    }
    int sum=0,flag=0;
    for(int i=1;i<=m;i++){
        if(i>1&&map[1][i].v<map[1][i-1].v) continue;
        if(i<m&&map[1][i].v<map[1][i+1].v) continue;
        memset(vis,0,sizeof(vis));
        bfs(i,1,i);
    }
    for(int i=1;i<=m;i++){
        if(!bo[i]){
            flag=1;sum++;
        }
    }
    if(flag){printf("0\n%d\n",sum);return 0;}
    printf("1\n");
    for(int i=1;i<=m;i++){
        for(int j=l[i];j<=r[i];j++){
            if(f[j]>f[l[i]-1]+1||!f[j])
                f[j]=f[l[i]-1]+1;
        }
    }
    printf("%d\n",f[m]);
    return 0;
}

AC代码:

dfs便捷版

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 1010
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
int bo[N],vis[N][N],map[N][N],l[N],r[N],f[N];
int n,m;
void dfs(int s,int x,int y){
    if(x==n){
        bo[y]=1;
        if(y<l[s]||!l[s]) l[s]=y;
        if(y>r[s]) r[s]=y;
    }
    int h=map[x][y];
    vis[x][y]=1;
    if(x<n&&map[x+1][y]<h&&!vis[x+1][y]) dfs(s,x+1,y);
    if(x>1&&map[x-1][y]<h&&!vis[x-1][y]) dfs(s,x-1,y);
    if(y<m&&map[x][y+1]<h&&!vis[x][y+1]) dfs(s,x,y+1);
    if(y>1&&map[x][y-1]<h&&!vis[x][y-1]) dfs(s,x,y-1);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&map[i][j]);
        }
    }
    int sum=0,flag=0;
    for(int i=1;i<=m;i++){
        if(i>1&&map[1][i]<map[1][i-1]) continue;
        if(i<m&&map[1][i]<map[1][i+1]) continue;
        memset(vis,0,sizeof(vis));
        dfs(i,1,i);
    }
    for(int i=1;i<=m;i++){
        if(!bo[i]){
            flag=1;sum++;
        }
    }
    if(flag){printf("0\n%d\n",sum);return 0;}
    printf("1\n");
    for(int i=1;i<=m;i++){
        for(int j=l[i];j<=r[i];j++){
            if(f[j]>f[l[i]-1]+1||!f[j])
                f[j]=f[l[i]-1]+1;
        }
    }
    printf("%d\n",f[m]);
    return 0;
}

bfs麻烦版

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 510
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
int bo[N],vis[N][N],l[N],r[N],f[N];
struct node{
    int x,y,v;
}map[N][N];
int n,m;
int bfs(int s,int x,int y){
    queue<node>que;
    que.push(map[x][y]);
    while(!que.empty()){
        node h=que.front();que.pop();
        for(int i=0;i<4;i++){
            int xx=h.x+dx[i],yy=h.y+dy[i];
            if(!vis[xx][yy]&&h.v>map[xx][yy].v&&xx>0&&xx<=n&&yy>0&&yy<=m){
                vis[xx][yy]=1;
                que.push(map[xx][yy]);
                if(xx==n){
                    bo[yy]++;
                    if(yy<l[s]||!l[s]) l[s]=yy;
                    if(yy>r[s]) r[s]=yy;
                }
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&map[i][j].v);
            map[i][j].x=i;map[i][j].y=j;
        }
    }
    int sum=0,flag=0;
    for(int i=1;i<=m;i++){
        if(i>1&&map[1][i].v<map[1][i-1].v) continue;
        if(i<m&&map[1][i].v<map[1][i+1].v) continue;
        memset(vis,0,sizeof(vis));
        bfs(i,1,i);
    }
    for(int i=1;i<=m;i++){
        if(!bo[i]){
            flag=1;sum++;
        }
    }
    if(flag){printf("%d\n%d\n",n==1?1:0,sum);return 0;}//这里还需要特判n=1时,可能是bfs的缺陷
    printf("1\n");
    for(int i=1;i<=m;i++){
        for(int j=l[i];j<=r[i];j++){
            if(f[j]>f[l[i]-1]+1||!f[j])
                f[j]=f[l[i]-1]+1;
        }
    }
    printf("%d\n",f[m]);
    return 0;
}

-----------------------------------------------------------------------------------------------------------------------------------------------

华丽的分割线

------------------------------------------------------------------------------------------------------------------------------------------------

反思:1、标志位设错,就会TLE,(考试代码为什么写一维的vis[],白白少了20分);

   2、简单搜索时,建议用dfs(至少不用特判(坑爹的出题人,~~~~(>_<)~~~~));

时间: 2024-09-30 19:28:15

7.3模拟比赛的相关文章

体育竞技模拟比赛

乒乓球比赛基本规则: 一方首先具有发球权,双方连续击打,球落地则该回合结束.如果输掉这一回合的是发球方,双方均不加分,但发球权要交给另一方.如果发球方赢得了这一回合,则发球方赢得1分,并继续拥有发球权.比赛总共进行n 局.一局比赛中,先得11分的一方为胜方,10平后,先多得2分得一方为胜方,胆大的淘汰赛采用七局四胜制,双打的淘汰赛和团体赛采用五局三胜制. 采用自顶向下的程序设计 步骤一:打印程序的介绍性信息 步骤二:获得运行需要的参数,即porbA,porbB,n 步骤三:利用球员A和B得能力值

模拟美式橄榄球比赛数据(R)

获得和清洗数据: 1.从网络上抓取数据 year<-2013 url<-paste("http://sports.yahoo.com/nfl/stats/byteam?group=Offense&cat=Total&conference=NFL&year=season_",year,"&sort=530&old_category=Total&old_group=Offense") offense<-r

Codeforces 730A:Toda 2(multiset模拟)

http://codeforces.com/problemset/problem/730/A 题意:有n个人打天梯,想让这n个人的分数相同,每场比赛必须有2-5个人参赛,参赛的人会降低一分,问一个合理方案让所有人的分数相同. 思路:不限制比赛场数,那么只用考虑2-3个人参赛的情况(因为4和5可以由2和3组成).但是这个时候就不知道什么时候用3什么时候用2了.. 看别人代码.只有最大的三个数是一样的时候才用3,其他时候都用2. 然后很暴力地用multiset来模拟比赛. 1 #include <b

0709模拟题

7.9模拟比赛 注:本场考试3道题,时间3个小时.全部为codevs上的题目 1.2124 美丽的大树 题目描述 Description 平江路是苏州最美丽的道路,路中间的绿化带上种了两行漂亮的大树,每行50棵,一共100棵大树,这些大树被编上了号,编号方式如下: 1 3 5 7 ………… 45 47 49 …………99     第一行 2 4 6 8 ………… 46 48 50 …………100    第二行 但是昨天晚上却发生了一件令人震惊的大事--可恶的破坏分子竟然偷去了这100棵大树中的一

ZROI提高组模拟赛05总结

ZROI提高组模拟赛05总结 感觉是目前为止最简单的模拟赛了吧 但是依旧不尽人意... T1 有一半的人在30min前就A掉了 而我花了1h11min 就是一个简单的背包,我硬是转化了模型想了好久,生生把一个弱智题变成了一个不可做题 最后竟然在转化两次后的模型上以为自己做出来了 这个题比别人多花的1h左右的时间,而且只得到了30分,成为了这场比赛失败的关键因素 T2 依旧是一道简单题 有人20min之内就A掉了 感觉放在CF里最多算一道Div2 D,还是简单的那种 可是我又一次想复杂了 大意就是

预测球队比赛成绩

1.体育竞技分析: 体育竞技分析:模拟N场比赛计算思维:抽象 + 自动化模拟:抽象比赛过程,自动模拟N场比赛,当N越大时,比赛结果分析越科学. 2.比赛规则:(以排球为例) 赛制规定: 排球前4局比赛采用25分制,每队只有赢得至少25分,并同时超过对方2分时 ,才胜1局.正式比赛采用5局3胜制,决胜局的比赛采用15分制,一队先得8分后,两队交换场区,按原位置顺序继续比赛到结束.在决胜局(第五局)之比赛,先获15分并领先对方2分为胜. 3.思维方式: 自顶向下即将一个复杂问题分解成几个问题,再细分

用python进行对乒乓球的比赛分析,并且将该程序进行封装

2.单打的淘汰赛采用七局四胜制,双打淘汰赛和团体赛采用五局三胜制.重点:        思维方式:自顶向下即将一个复杂问题分解成几个问题,再细分成一个个具体的小问题,从而来解决复杂问题.自底向上为自顶向下的逆过程,即解决复杂问题的方法,逐步解决一个个小问题,来达成目的. 2.将体育竞技分析分解为以下几个小步骤 1.打印程序的介绍性信息式2.获得程序运行参数:probA(A的能力值),probB(B的能力值),n(比赛场次)3.利用球员AB的能力值,模拟n场比赛4.输出球员AB获胜的场次及概率 3

【python】羽毛球竞技模拟

一.体育竞技模拟分析简要介绍 体育竞技模拟分析,是个IPO问题,大致过程如下: 输入:两个球员(球员A和B)的能力概率,模拟比赛的场次 处理:模拟比赛过程 输出:球员A和B分别赢得球赛的概率 二.程序设计方法 程序设计有自顶向下和自底向上两种方法,此处重点介绍自顶向下. 自顶向下的基本思想:以一个总问题出发,试图把它表达为很多小问题组成的解决方案,再用同样的技术依次攻破每个小问题,最终问题变得非常小,也就是化整为零.然后把所有的碎片组合起来,就可以得到一个程序. 自顶向下设计: 1.顶层设计 体

预测乒乓球比赛成绩

我们通过自顶向下,从简到难的方式进行一步步地分解,设计比赛的代码 下面是通过分析乒乓球比赛所设计出的代码: from random import randomdef printIntro(): print("这个程序模拟两个选手A和B的乒乓球赛") print("程序运行需要A和B的能力值(0到1之间)")def getInputs(): a=eval(input("请输入选手A的能力值(0-1):")) b=eval(input("请