考前模拟冲刺2

 

1. 足球联赛
(soccer.pas/c/cpp )

题目描述:

巴蜀中学新一季的足球联赛开幕了。足球联赛有 n只球队参赛,每赛季,每只球队要与其他球队各赛两场,主客各一场,赢一场得 3 分,输一场不得分,平局两只队伍各得一分。

英勇无畏的小鸿是机房的主力前锋,她总能在关键时刻踢出一些匪夷所思的妙球。但是很可惜,她过早的燃烧完了她的职业生涯,不过作为一个能够 Burning 的 girl,她的能力不止如此,她还能预测这个赛季所有球队的比赛结果。

虽然她能准确预测所有比赛的结果,但是其实她不怎么厉害,Mr.Gao 上数学课时她总是在 sleep,因此她的脑里只有整数没有实数,而且,她只会 10 以内非负整数的加法运算,因此她只有结果却无法知道谁会获得联赛的冠军。

小鸿想给冠军队伍的所有队员一个拥抱,所以她把计算结果的任务交给了你:现在,给你一个 n*n 的矩阵表示比赛情况。第 i 行第 j 列的字母表示在第 i 只队伍 在主场迎战第 j 只队伍的比赛情况,W 表示主队赢,L 表示主队输,D 表示平局。现在需要你给出最后能得到小鸿拥抱的队伍编号,如有多支队伍分数最高,按字典序输出编号。

输入格式:

 

第一行一个整数 n。 
接下来 n 行,每行 n 个字符,表示输赢情况。第 i 行第 i 列为 - ,因为一只队伍不可能与自己比赛。

输出格式:

输出得分最高的队伍编号。如有多个在一行中输出,用一个空格分开。

样例输入:


  样例1

3
-WW
W-W
WW-

  样例2

5
-DWWD
L-WLL
DD-WD
DDL-L
DDLL- 

样例输出:

  样例1

123

  样例2

 

1

 

数据范围:

对于 40%的数据,满足 N<=20 
对于 100%的数据,满足 N<=50

思路:暴力即可,水题。但是没有注意胜利是加3分,所以gg了┭┮﹏┭┮,下次要细心啊!!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
char s[60];
struct nond{
    int num,id;
}v[60];
int cmp(nond a,nond b){
    if(a.num==b.num)    return a.id<b.id;
    return a.num>b.num;
}
int main(){
    freopen("soccer.in","r",stdin);
    freopen("soccer.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        v[i].id=i;
        for(int j=1;j<=n;j++){
            if(s[j]=='D'){ v[i].num+=1;v[j].num+=1; }
            else if(s[j]=='W'){ v[i].num+=3; }
            else if(s[j]=='L'){ v[j].num+=3; }
        }
    }
    sort(v+1,v+1+n,cmp);
    for(int i=1;i<=n;i++)
        if(v[i].num==v[1].num)    cout<<v[i].id<<" ";
    return 0;
}

2. 最短路径
(paths.pas/c/cpp )

 

题目描述:

平面内给出 n 个点,记横坐标最小的点为 A,最大的点为 B,现在小 Y 想要知道在
每个点经过一次(A 点两次)的情况下从 A 走到 B,再回到 A 的最短路径。但他是个强
迫症患者,他有许多奇奇怪怪的要求与限制条件:
1.从 A 走到 B 时,只能由横坐标小的点走到大的点。
2.由 B 回到 A 时,只能由横坐标大的点走到小的点。
3.有两个特殊点 b1 和 b2, b1 在 0 到 n-1 的路上,b2 在 n-10 的路上。
请你帮他解决这个问题助他治疗吧!

输入格式:

 第一行三个整数 n,b1,b2,( 0 < b1,b2 < n-1 且 b1 <> b2)。n 表示点数,从 0 到 n-1 编号,b1 和 b2 为两个特殊点的编号。
    以下 n 行,每行两个整数 x、y 表示该点的坐标(0 <= x,y <= 2000),从 0 号点顺序给出。Doctor Gao 为了方便他的治疗,已经将给出的点按 x 增序排好了。

输出格式:

输出仅一行,即最短路径长度(精确到小数点后面 2 位)

样例输入:

5 1 3
1 3
3 4
4 1
7 5
8 3

样例输出:

18.18

样例解释:

最短路径:0->1->4->3->2->0

数据范围:

20%的数据 n<=20
60%的数据 n<=300
100%的数据 n<=1000
对于所有数据 x,y,b1,b2 如题目描述.

 

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1001
using namespace std;
int n,b1,b2;
struct nond{
    int x,y;
}cnt[MAXN];
int vis[MAXN];
double bns,ans=0x7f7f7f7f;
double dis[MAXN][MAXN];
void slove(){
    int pre=1;bns=0;
    for(int i=pre+1;i<=n;i++)
        if(!vis[i]||i==n){
            bns+=dis[pre][i];
            pre=i;
        }
}
void dfs(double sum,int pre){
    if(vis[b2])    return ;
    if(pre>b1&&!vis[b1])    return ;
    if(pre==n){
        if(!vis[1]||!vis[b1]||vis[b2]==1||!vis[n])    return ;
        slove();
        ans=min(sum+bns,ans);
        return ;
    }
    for(int i=pre+1;i<=n;i++)
        if(!vis[i]){
            vis[i]=1;
            dfs(sum+dis[pre][i],i);
            vis[i]=0;
        }
}
int main(){
    freopen("paths.in","r",stdin);
    freopen("paths.out","w",stdout);
    scanf("%d%d%d",&n,&b1,&b2);b1+=1;b2+=1;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&cnt[i].x,&cnt[i].y);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            dis[i][j]=dis[j][i]=sqrt((cnt[i].x-cnt[j].x)*(cnt[i].x-cnt[j].x)+(cnt[i].y-cnt[j].y)*(cnt[i].y-cnt[j].y));
    dfs(0,0);
    printf("%.2lf",ans);
}
20分的暴力

正解思路:动态规划

(定义dis[i][j]表示点i到点j之间的直线距离)
把问题简化 后可以发现,问题其实可以看成这样一个问题:平面上n个点,确定一条连接各点的最短闭合旅程,这种旅程即为从最左点开始,严格地从左到右直至最右点,然后严格地从右到左直至出发点。
然后不妨把问题中从n到1路线看成是从1到n的路线,这样我们就有了两条从1到n的路线。 定义f[i][j]表示从点i到点j的路径,理解为:从点i开始,从右到左一直到点1,然后从左到右一直到点j。在这个路径上,会经过点1到点max(i,j)之间的所有点且只经过一次。
可以列出状态转移方程为:
定义k为max(i,j)+1;
f[1][1]=0;
f[i][k]=min(f[i][k],f[i][j]+dis[j][k]);
f[k][j]=min(f[k][j],f[i][j]+dis[i][k]);
还要考虑一些特殊情况,比如:
  点b1,b2。
  还有k=max(i,j)+1;(i==n||j==n)的情况。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1001
using namespace std;
int n,b1,b2;
struct nond{
    int x,y;
}cnt[MAXN];
double dis[MAXN][MAXN],f[MAXN][MAXN];
int main(){
    freopen("paths.in","r",stdin);
    freopen("paths.out","w",stdout);
    scanf("%d%d%d",&n,&b1,&b2);b1+=1;b2+=1;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&cnt[i].x,&cnt[i].y);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            dis[i][j]=dis[j][i]=sqrt((cnt[i].x-cnt[j].x)*(cnt[i].x-cnt[j].x)+(cnt[i].y-cnt[j].y)*(cnt[i].y-cnt[j].y));
    memset(f,0x7f,sizeof(f));
    f[1][1]=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(i!=j||i==1){
                int k=max(i,j)+1;
                if(k-1==n){
                    if(i!=n)    f[n][n]=min(f[n][n],f[i][j]+dis[i][n]);
                    if(j!=n)    f[n][n]=min(f[n][n],f[i][j]+dis[j][n]);
                    continue;
                }
                if(k!=b1)    f[i][k]=min(f[i][k],f[i][j]+dis[j][k]);
                if(k!=b2)    f[k][j]=min(f[k][j],f[i][j]+dis[i][k]);
            }
    printf("%.2lf",f[n][n]);
}

3.阿 Q 的停车场
(park.pas/c/cpp )

题目描述:

刚拿到驾照的 KJ 总喜欢开着车到处兜风,玩完了再把车停到阿 Q 的停车场里,虽然她对自己停车的水平很有信心,但她还是不放心其他人的停车水平,尤其是 Kelukin。
于是,她每次都把自己的爱车停在距离其它车最远的一个车位。KJ 觉得自己这样的策略非常科学,于是她开始想:在一个停车场中有一排车位,从左到右编号为
1 到 n,初始时全部是空的。
有若干汽车,进出停车场共 m 次。对于每辆进入停车场的汽车,会选择与其它车距离最小值最大的一个车位,若有多个符合条件,选择最左边一个。
KJ 想着想着就睡着了,在她一旁的 Kelukin 想帮她完成这个心愿,但是他又非常的懒,不愿意自己动手,于是就把这个问题就留给了你:
在 KJ 理想的阿 Q 的停车场中,给你车辆进出的操作序列,依次输出每辆车的车位编号。

输入格式:

第一行,两个整数 n 和 m,表示停车场大小和操作数;
接下来 m 行,每行两个整数 F 和 x
F 是 1 表示编号为 x 的车进停车场;
F 是 2 表示编号为 x 的车出停车场;
保证操作合法,即:
出停车场的车一定目前仍在停车场里;
停车场内的车不会超过 n;

输出格式:

对于所有操作 1,输出一个整数,表示该车车位的编号。

样例输入:

7 11
1 15
1 123123
1 3
1 5
2 123123
2 15
1 21
2 3
1 6
1 7
1 8

样例输出:

1
7
4
2
7
4
1
3

数据范围:

30%的数据 n<=1000 ,m<=100060%的数据 n<=200000,m<=2000100%的数据 n,m<=200000,车的编号小于等于 10^6

 

#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 200010
using namespace std;
map<int,int>ma;
int n,m,tot;
int vis[MAXN],stop[MAXN];
struct nond{
    int now,l,r;
    int len,ren,sum;
    int ll,rr,sum1,sum2;
}tree[MAXN*4];
void up(int now){
//    if(tree[now*2].l==1)
    if(tree[now*2].sum>=tree[now*2+1].sum)
        tree[now].sum=tree[now*2].sum,tree[now].sum1=tree[now*2].sum1,tree[now].sum2=tree[now*2].sum2;
    else
        tree[now].sum=tree[now*2+1].sum,tree[now].sum1=tree[now*2+1].sum1,tree[now].sum2=tree[now*2+1].sum2;
    if(tree[now*2].ren+tree[now*2+1].len>tree[now].sum)
        tree[now].sum=tree[now*2].ren+tree[now*2+1].len,tree[now].sum1=tree[now*2].rr,tree[now].sum2=tree[now*2+1].ll;
    else if(tree[now*2].ren+tree[now*2+1].len==tree[now].sum)
        if(tree[now*2].rr<tree[now].sum1&&tree[now*2].rr!=0)
            tree[now].sum1=tree[now*2].rr,tree[now].sum2=tree[now*2+1].ll;
    tree[now].len=tree[now*2].len;
    tree[now].ll=tree[now*2].ll;
    tree[now].ren=tree[now*2+1].ren;
    tree[now].rr=tree[now*2+1].rr;
    if(tree[now].ll>=tree[now].sum1&&tree[now].sum2>=tree[now].rr){
        tree[now].sum=tree[now].len=tree[now].ren=tree[now].r-tree[now].l+1;
        tree[now].ll=tree[now].sum2=tree[now].r;
        tree[now].rr=tree[now].sum1=tree[now].l;
    }
    else if(tree[now].ll>=tree[now].sum1){
        tree[now].sum=tree[now].len=tree[now].sum2-tree[now].l+1;
        tree[now].sum1=tree[now].l;
        tree[now].ll=tree[now].sum2;
    }
    else if(tree[now].sum2>=tree[now].rr){
        tree[now].sum=tree[now].ren=tree[now].r-tree[now].sum1+1;
        tree[now].sum2=tree[now].r;
        tree[now].rr=tree[now].sum1;
    }
}
void build(int now,int l,int r){
    tree[now].l=l;
    tree[now].r=r;
    if(tree[now].l==tree[now].r){
        tree[now].len=1;
        tree[now].ren=1;
        tree[now].sum=1;
        tree[now].ll=tree[now].r;
        tree[now].rr=tree[now].l;
        tree[now].sum1=tree[now].l;
        tree[now].sum2=tree[now].r;
        return ;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
    up(now);
}
void change(int now,int x,int k){
    if(tree[now].l==tree[now].r){
        if(k==1){
            tree[now].ll=0;
            tree[now].rr=0;
            tree[now].sum1=0;
            tree[now].sum2=0;
            tree[now].sum=0;
            tree[now].len=0;
            tree[now].ren=0;
        }
        if(k==0){
            tree[now].sum=1;
            tree[now].len=1;
            tree[now].ren=1;
            tree[now].ll=tree[now].r;
            tree[now].rr=tree[now].l;
            tree[now].sum1=tree[now].l;
            tree[now].sum2=tree[now].r;
        }
        return ;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    if(x<=mid)    change(now*2,x,k);
    else if(x>mid)    change(now*2+1,x,k);
    up(now);
}
int main(){
    freopen("park.in","r",stdin);
    freopen("park.out","w",stdout);
    scanf("%d%d",&n,&m);
    if(n<=1000&&m<=1000){
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            if(x==1){
                ma[y]=++tot;
                int len=0,pos,maxn=-1,l;
                for(int j=1;j<=n;j++){
                    if(!vis[j])    len++;
                    else{
                        if(len==0)    continue;
                        if(j-len==1){ maxn=len-1;l=len;pos=1; }
                        else{
                            int k=(len-1)/2;
                            if(k>maxn){ maxn=k;l=len;pos=j-len; }
                        }
                        
                        len=0;
                    }
                }
                if((len-1)/2>maxn){ maxn=(len-1)/2;l=len;pos=n-len+1; }
                int last=pos+l-1,mid=(pos+last)/2;
                if(pos==1)    vis[pos]=1,stop[tot]=pos,cout<<pos<<endl;
                else if(last==n)    vis[last]=1,stop[tot]=last,cout<<last<<endl;
                else if(pos!=1&&last!=n)    vis[mid]=1,stop[tot]=mid,cout<<mid<<endl;
            }
            if(x==2)    vis[stop[ma[y]]]=0;
        }
    }
    else if(n<=200000&&m<=2000){
        build(1,1,n);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            if(x==1){
                ma[y]=++tot;
                int len=0,pos=0;
                if(tree[1].len)
                    len=tree[1].len,pos=1;
                if(tree[1].ren>len)
                    len=tree[1].ren,pos=tree[1].r;
                if((tree[1].sum-1)/2>len)
                    len=tree[1].sum,pos=(tree[1].sum2-tree[1].sum1)/2;
                change(1,pos,1);
                stop[tot]=pos;
                cout<<pos<<endl;
            }
            else    change(1,stop[ma[y]],0);
        }
    }
}
10分的暴力
/*
维护的区间中间最长的
区间从左边开始向右能拓展到的最长的。
区间从右边开始向左能拓展到的最长的。
然后没有调出来处理。 
*/
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 200010
using namespace std;
map<int,int>ma;
int n,m,tot;
int vis[MAXN],stop[MAXN];
struct nond{
    int now,l,r;
    int len,ren,sum;
    int ll,rr,sum1,sum2;
}tree[MAXN*4];
void up(int now){
    if(tree[now*2].sum>=tree[now*2+1].sum)
        tree[now].sum=tree[now*2].sum,tree[now].sum1=tree[now*2].sum1,tree[now].sum2=tree[now*2].sum2;
    else
        tree[now].sum=tree[now*2+1].sum,tree[now].sum1=tree[now*2+1].sum1,tree[now].sum2=tree[now*2+1].sum2;
    if(tree[now*2].ren+tree[now*2+1].len>tree[now].sum)
        tree[now].sum=tree[now*2].ren+tree[now*2+1].len,tree[now].sum1=tree[now*2].rr,tree[now].sum2=tree[now*2+1].ll;
    else if(tree[now*2].ren+tree[now*2+1].len==tree[now].sum)
        if(tree[now*2].rr<tree[now].sum1&&tree[now*2].rr!=0)
            tree[now].sum1=tree[now*2].rr,tree[now].sum2=tree[now*2+1].ll;
    
    tree[now].len=tree[now*2].len;
    tree[now].ll=tree[now*2].ll;
    tree[now].ren=tree[now*2+1].ren;
    tree[now].rr=tree[now*2+1].rr;
    
    if(tree[now].ll>=tree[now].sum1&&tree[now].sum2>=tree[now].rr&&tree[now].ll!=0&&tree[now].rr!=0){
        tree[now].sum=tree[now].len=tree[now].ren=tree[now].r-tree[now].l+1;
        tree[now].ll=tree[now].sum2=tree[now].r;
        tree[now].rr=tree[now].sum1=tree[now].l;
    }
    else if(tree[now].ll>=tree[now].sum1&&tree[now].sum1!=0&&tree[now].ll!=0){
        tree[now].sum=tree[now].len=tree[now].sum2-tree[now].l+1;
        tree[now].sum1=tree[now].l;
        tree[now].ll=tree[now].sum2;
    }
    else if(tree[now].sum2>=tree[now].rr&&tree[now].rr!=0&&tree[now].sum2!=0){
        tree[now].sum=tree[now].ren=tree[now].r-tree[now].sum1+1;
        tree[now].sum2=tree[now].r;
        tree[now].rr=tree[now].sum1;
    }
}
void build(int now,int l,int r){
    tree[now].l=l;
    tree[now].r=r;
    if(tree[now].l==tree[now].r){
        tree[now].len=1;
        tree[now].ren=1;
        tree[now].sum=1;
        tree[now].ll=tree[now].r;
        tree[now].rr=tree[now].l;
        tree[now].sum1=tree[now].l;
        tree[now].sum2=tree[now].r;
        return ;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
    up(now);
}
void change(int now,int x,int k){
    if(tree[now].l==tree[now].r){
        if(k==1){
            tree[now].ll=0;
            tree[now].rr=0;
            tree[now].sum1=0;
            tree[now].sum2=0;
            tree[now].sum=0;
            tree[now].len=0;
            tree[now].ren=0;
        }
        if(k==0){
            tree[now].sum=1;
            tree[now].len=1;
            tree[now].ren=1;
            tree[now].ll=tree[now].r;
            tree[now].rr=tree[now].l;
            tree[now].sum1=tree[now].l;
            tree[now].sum2=tree[now].r;
        }
        return ;
    }
    int mid=(tree[now].l+tree[now].r)/2;
    if(x<=mid)    change(now*2,x,k);
    else if(x>mid)    change(now*2+1,x,k);
    up(now);
}
int main(){
    freopen("park.in","r",stdin);
    freopen("park.out","w",stdout);
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        if(x==1){
            ma[y]=++tot;
            int len=0,pos=0,flag=0;
            if(tree[1].len)    len=tree[1].len-1,pos=1,flag=1;
            if(tree[1].ren-1>len)    len=tree[1].ren-1,pos=tree[1].r,flag=1;        
            if((tree[1].sum-1)/2>len)    len=tree[1].sum,pos=(tree[1].sum2+tree[1].sum1)/2;
            else if((tree[1].sum-1)/2==len&&!flag)    len=tree[1].len,pos=(tree[1].sum1+tree[1].sum2)/2;    
            change(1,pos,1);
            stop[tot]=pos;
            cout<<pos<<endl;
        }
        else    change(1,stop[ma[y]],0);
    }
}
没调出来的线段树
#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;

const int N=200002;
struct node{
    int x,y,mid,p;
};
node tree[N<<4];
int n,m;
int car[1000001];  //车的位置,如果你6可以加离散化啊 

void update(int bh)
{
    int lc=bh<<1;
    int rc=(bh<<1)+1;
    if (bh)
    {
        tree[bh].x=tree[lc].x;
        tree[bh].y=tree[rc].y;
        tree[bh].mid=tree[lc].mid;
        tree[bh].p=tree[lc].p;
        if (tree[rc].mid>tree[bh].mid)
        {
            tree[bh].mid=tree[rc].mid;  tree[bh].p=tree[rc].p;
        }
        int l=tree[rc].y-tree[lc].x+1;  //两个区间之间的空位
        if (l>tree[bh].mid)
        {
            tree[bh].mid=l;
            tree[bh].p=(tree[lc].y+tree[rc].x)>>1;
        } 
    }
    return;
}

void add(int bh,int l,int r,int wz,int z)
{
    if (l==wz&&l==r)
    {
        if (z==1)
        {
            tree[bh].x=l;
            tree[bh].y=r;
            tree[bh].mid=0;   //节点上有车了,当然就没有mid和p值了 
            tree[bh].p=0;
            return;
        }
        else
        {
            tree[bh].x=0;
            tree[bh].y=0;
            tree[bh].mid=0;
            tree[bh].p=0;
            return;
        }

    }
    int mid=(l+r)>>1;
    if (wz<=mid) add(bh<<1,l,mid,wz,z);
    if (wz>mid) add((bh<<1)+1,mid+1,r,wz,z);
    update(bh);
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int opt,u;
        scanf("%d%d",&opt,&u);
        if (opt==1)
        {
            if (tree[1].x==0)  //整颗线段树的信息都集中在根节点 
            {
                car[u]=1;  //整个停车场都是空的 
            }
            else
            {
                int mx=-1;
                if (tree[1].x-1>mx)
                {
                    mx=tree[1].x-1;
                    car[u]=1;  //第一个车位没人停 
                }
                if (tree[1].mid>mx)   
                {
                    mx=tree[1].mid;
                    car[u]=tree[1].p;
                }
                if (n-tree[1].y>mx)
                {   //最后的车位没人停 
                    mx=n-tree[1].y;
                    car[u]=n;
                }
            }
            printf("%d\n",car[u]);
            add(1,1,n,1,1); 
        }
        else
        {
            add(1,1,n,car[u],-1);  //出停车场 
        }
    }
    return 0;
}
std

 

posted @ 2017-11-08 15:52  一蓑烟雨任生平  阅读(411)  评论(3编辑  收藏  举报