zoukankan      html  css  js  c++  java
  • 冲刺Noip2017模拟赛4 解题报告——五十岚芒果酱

    题1 韬韬抢苹果(apple)

    【问题描述】
    又到了收获的季节,树上结了许多韬韬,错了,是许多苹果,有很多个小韬韬都来摘苹
    果。每个韬韬都想要最大的苹果,所以发生了争执,为了解决他们的矛盾,出题人定了一项
    特殊的规则,按体重的大小来定顺序,每一轮都是先由胖的先摘(照顾胖子),每个韬韬都
    是很聪明的,不会错过眼前最大的苹果。现在问题来了,一共有 n 个苹果,m 个韬韬,要你
    按原顺序输出每个韬韬可以抢到的苹果的总大小。
    【输入格式】apple.in
    第一行两个数 n,m。
    接下来一行 n 个数,分别为每个苹果的大小。
    接下来一行 m 个数,分别为每个韬韬的体重。
    【输出格式】apple.out
    一行 m 个数,每个韬韬抢到的苹果的大小。
    【输入样例】
    5 3
    1 2 3 4 5
    1 2 3
    【输出样例】
    3 5 7
    【 数据规模 】
    n,m<=100000
    题目

     tag:模拟

     思路:模拟即可,为了防止被极端数据卡开了long long。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cmath>
     6 #define ll long long
     7 #define maxn 100010
     8 using namespace std;
     9 ll ans[maxn];
    10 int ap[maxn],po,n,m;
    11 struct TT{
    12     int w,id;
    13 }tt[maxn];
    14 bool cmp1(int x,int y)
    15 {
    16     return x>y;
    17 }
    18 bool cmp2(TT x,TT y)
    19 {
    20     return x.w>y.w;
    21 }
    22 int main()
    23 {
    24     //freopen("apple.in","r",stdin);
    25     //freopen("apple.out","w",stdout);
    26     scanf("%d%d",&n,&m);
    27     for(int i=1;i<=n;++i) scanf("%d",&ap[i]);
    28     for(int i=1;i<=m;++i){
    29         scanf("%d",&tt[i].w);
    30         tt[i].id=i;
    31     }
    32     sort(ap+1,ap+n+1,cmp1);
    33     sort(tt+1,tt+m+1,cmp2);
    34     int f=po=1;
    35     while(1){
    36         for(int i=1;i<=m;++i){
    37             ans[tt[i].id]+=ap[po++];
    38             if(po>n){
    39                 f=0;
    40                 break;
    41             }
    42         }
    43         if(!f) break;
    44     }
    45     for(int i=1;i<=m;++i) cout<<ans[i]<<" ";
    46     return 0;
    47 }

    题2  开场舞蹈(dance)

    【问题描述】
    在全世界人民的期盼下,2008 年北京奥林匹克运动会终于隆重召开了!
    为了展示中华民族博大精深的优秀传统文化,负责开幕式开场舞蹈的编排人员一丝不
    苟,每一个细节都力争完美。关于队伍是采用“天圆”阵还是“地方”阵的问题,大家讨论
    了七天七夜,仍没有结果。于是,他们希望借助计算机,计算两种阵型的成本。
    队伍将排列在一个二维平面内,且必须以(00)点为中心使得队伍保持对称美。“天
    圆”阵是一个圆形,而“地方”阵则是一个边平行于坐标轴的正方形。由于某种因素,阵型
    要求覆盖某些点(可以在边上)。
    你的任务是,计算出能够覆盖这些点的两种阵型的最小面积。
    【输入文件】
    输入文件  dance.in。第一行是一个整数 n(1<=n<=100000),表示需要覆盖的点的个数。
    接下来 n 行,第 i 行是两个整数 xi,yi(-1000<=xi,yi<=1000),表示第 i 个点的坐标位
    置(xi,yi)。
    【输出文件】
    输出文件  dance.out。第一行是一个整数 s1,表示能够覆盖这些点的“天圆”阵的最小
    面积(pi=3.14,四舍五入)。第二行是一个整数 s2,表示能够覆盖这些点的“地方”阵的
    最小面积。
    【样例输入】
    4
    0 0
    0 2
    5 0
    8 0
    【样例输出】
    201
    256
    题目

    tag:模拟

    思路:取最大值,注意四舍五入的处理,乘10取整,再将mod10的结果与5比较。还有更简单的方法,加上0.5再取整。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cmath>
     6 #define ll long long
     7 #define maxn 100010
     8 using namespace std;
     9 const double pi=3.14;
    10 int n,A,ans;
    11 double R;
    12 double cal(int x,int y){return sqrt((double)(x*x+y*y));}
    13 int main()
    14 {
    15     //freopen("dance.in","r",stdin);
    16     //freopen("dance.out","w",stdout);
    17     int x,y;
    18     scanf("%d",&n);
    19     for(int i=1;i<=n;++i){
    20         scanf("%d%d",&x,&y);
    21         R=max(R,cal(x,y));
    22         A=max(A,max(abs(x),abs(y)));
    23     }
    24     y=(int)(R*R*pi*10);
    25     ans=y/10;
    26     if(y%10>=5) ans++;
    27     printf("%d
    ",ans);
    28     printf("%d
    ",A*A*4);
    29     return 0;
    30 }

    题3 架设电话线(phoneline)

    【 问题描述 】
    Farmer John 打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。
    于是,FJ 必须为此向电信公司支付一定的费用。
    FJ 的农场周围分布着 N(1 <= N <= 1,000)根按 1..N 顺次编号的废弃的电话线杆,任意两
    根电话线杆间都没有电话线相连。一共 P(1 <= P <= 10,000)对电话线杆间可以拉电话线,其
    余的那些由于隔得太远而无法被连接。
    第 i 对电话线杆的两个端点分别为 A_i、B_i,它们间的距离为 L_i (1 <= L_i <=
    1,000,000)。数据中保证每对{A_i,B_i}最多只出现 1 次。编号为 1 的电话线杆已经接入了
    全国的电话网络,整个农场的电话线全都连到了编号为 N 的电话线杆上。也就是说,FJ 的
    任务仅仅是找一条将 1 号和 N 号电话线杆连起来的路径,其余的电话线杆并不一定要连入
    电话网络。
    经过谈判,电信公司最终同意免费为 FJ 连结 K(0 <= K < N)对由 FJ 指定的电话线杆。
    对于此外的那些电话线,FJ 需要为它们付的费用,等于其中最长的电话线的长度(每根电
    话线仅连结一对电话线杆)。如果需要连结的电话线杆不超过 K 对,那么 FJ 的总支出为 0。
    请你计算一下,FJ 最少需要在电话线上花多少钱。
    【输入格式】
    * 第 1 行: 3 个用空格隔开的整数:N,P,以及 K
    * 第 2..P+1 行: 第 i+1 行为 3 个用空格隔开的整数:A_i,B_i,L_i
    【输入样例】phoneline.in
    5 7 1
    1 2 5
    3 1 4
    2 4 8
    3 2 3
    5 2 9
    3 4 7
    4 5 6
    【输入说明】
    一共有 5 根废弃的电话线杆。电话线杆 1 不能直接与电话线杆 45 相连。电话线杆 5
    不能直接与电话线杆 13 相连。其余所有电话线杆间均可拉电话线。电信公司可以免费为
    FJ 连结一对电话线杆。
    【输出格式】
    * 第 1 行: 输出 1 个整数,为 FJ 在这项工程上的最小支出。如果任务不可能完成,输
    出-1
    【输出样例】phoneline.out
    4
    【输出说明】
    FJ 选择如下的连结方案:1->33->22->5,这 3 对电话线杆间需要的电话线的长度分
    别为 439。FJ 让电信公司提供那条长度为 9 的电话线,于是,他所需要购买的电话线的
    最大长度为 4
    题目

    tag:二分、最短路

    思路:由于对于路径的选择、寻找答案都有很大的不确定性,可以考虑二分答案x作划分免费和付费的分界线,它也是付费边的上限。如果选择的边比x大视作距离为1,否则距离为0,那么dis[n]就被赋予了新的意义——从点1到点n最少选择的大于x的边数,跑一遍SPFA再看dis[n]有没有超过k,大于k说明答案不成立,因为电话公司无论如何都要支付超过x的这么多边,要把上限提高使得dis[n]变小减轻电话公司的压力。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #define ll long long
     8 #define maxn 100010
     9 #define inf 1<<30
    10 using namespace std;
    11 int n,m,k,hl[1010],vis[1010],dis[1010],cnt,cs[20010];
    12 queue<int>Q;
    13 struct X{
    14     int u,v,w,ne;
    15 }e[20010];
    16 void add(int u,int v,int w)
    17 {
    18     e[++cnt].u=u;
    19     e[cnt].v=v;
    20     e[cnt].w=w;
    21     e[cnt].ne=hl[u];
    22     hl[u]=cnt;
    23 }
    24 void spfa()
    25 {
    26     memset(dis,127/3,sizeof(dis));
    27     dis[1]=0;
    28     vis[1]=1;
    29     Q.push(1);
    30     while(!Q.empty()){
    31         int u=Q.front();
    32         Q.pop();
    33         for(int i=hl[u];i;i=e[i].ne){
    34             int v=e[i].v;
    35             if(dis[v]>dis[u]+cs[i]){
    36                 dis[v]=dis[u]+cs[i];
    37                 if(!vis[v]){
    38                     vis[v]=1;
    39                     Q.push(v);
    40                 }
    41             }
    42         }
    43         vis[u]=0;
    44     }
    45 }
    46 bool div2(int x)
    47 {
    48     memset(cs,0,sizeof(cs));
    49     for(int i=1;i<=n;++i)
    50         for(int j=hl[i];j;j=e[j].ne)
    51             if(e[j].w>x) cs[j]=1;
    52     spfa();
    53     return dis[n]<=k;
    54 }
    55 bool cmp(int x,int y){
    56     return x>y;
    57 }
    58 int main()
    59 {
    60     //freopen("phoneline.in","r",stdin);
    61     //freopen("phoneline.out","w",stdout);
    62     int x,y,w;
    63     scanf("%d%d%d",&n,&m,&k);
    64     for(int i=1;i<=m;++i){
    65         scanf("%d%d%d",&x,&y,&w);
    66         add(x,y,w);
    67         add(y,x,w);
    68     }
    69     int l=0,r=1000001;
    70     while(l<r){
    71         int mid=(l+r)>>1;
    72         if(div2(mid)) r=mid;
    73         else l=mid+1;
    74     }
    75     r==1000001?printf("-1"):printf("%d
    ",r);
    76     return 0;
    77 }

    题4 洪水(slikar)

    【问题描述】
    一天,一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安全
    的。
    森林的地图由 R 行 C 列组成,空白区域用点“.”表示,洪水的区域用“*”表示,而
    岩石用“X”表示,另画家的住所用“D”表示,画家用“S”表示。
    有以下几点需要说明:
    1.每一分钟画家能向四个方向移动一格(上、下、左、右)
    2.每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)
    3.洪水和画家都不能通过岩石区域
    4.画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到
    的同时被洪水蔓延到了,这也是不允许的)
    5. 洪水蔓不到画家的住所。
    给你森林的地图,编写程序输出最少需要花费多长时间才能从开始的位置赶回家中。
    【输入】
    输入第一行包含两个整数 R 和 C(R,C<=50)。
    接下来 R 行每行包含 C 个字符(“.”、“*”、“X”、“D”或“S”)。地图保证只有一个“D”
    和一个“S”。
    【输出】
    输出画家最快安全到达住所所需的时间,如果画家不可能安全回家则输出“KAKTUS”。
    【输入输出样例 1 】
    slikar.in slikar.out
    3 3
    D.*
    ...
    .S.
    
    3
    【输入输出样例 2 】
    slikar.in slikar.out
    3 3
    D.*
    ...
    ..S
    
    KAKTUS
    【输入输出样例 3 】
    slikar.in slikar.out
    3 6
    D...*.
    .X.X..
    ....S.
    
    6
    题目

    tag:模拟/dfs、bfs/最短路

    思路:初始化所有点洪水出现的时间为无穷大,以每个“*”作基点向外dfs预处理更新时间(能取到最小值再扩展,此处算是剪枝),之后bfs走迷宫,到达的时间一定要先于洪水出现的时间,也可以二维转一维跑SPFA。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #define ll long long
     8 #define maxn 2510
     9 #define inf 707406378
    10 using namespace std;
    11 int dx[]={0,1,0,-1},dy[]={1,0,-1,0},n,m,cnt,dis[maxn],hl[maxn],MP[maxn],S,T,vis[maxn];
    12 char mp[60][60];
    13 queue<int>Q;
    14 struct X{
    15     int u,v,w,ne;
    16 }e[maxn*4];
    17 void add(int u,int v)
    18 {
    19     e[++cnt].u=u;
    20     e[cnt].v=v;
    21     e[cnt].ne=hl[u];
    22     hl[u]=cnt;
    23 }
    24 int cal(int x,int y){return (x-1)*m+y;}
    25 bool ok(int x,int y)
    26 {
    27     if(x>=1&&x<=n&&y>=1&&y<=m) return true;
    28     return false;
    29 }
    30 void dfs(int x,int y,int t)
    31 {
    32     if(!t||(ok(x,y)&&mp[x][y]=='.'&&t<MP[cal(x,y)])){
    33         MP[cal(x,y)]=t;
    34         for(int i=0;i<4;++i) dfs(x+dx[i],y+dy[i],t+1);
    35     }
    36 }
    37 bool spfa()
    38 {
    39     dis[S]=0;
    40     vis[S]=1;
    41     Q.push(S);
    42     while(!Q.empty()){
    43         int u=Q.front();
    44         Q.pop();
    45         for(int i=hl[u];i;i=e[i].ne){
    46             int v=e[i].v,aft=dis[u]+1;
    47             if(dis[v]>aft&&MP[v]>aft){
    48                 dis[v]=aft;
    49                 if(!vis[v]){
    50                     vis[v]=1;
    51                     Q.push(v);
    52                 }
    53             }
    54         }
    55         vis[u]=0;
    56     }
    57     if(dis[T]==inf) return false;
    58     return true;
    59 }
    60 int main()
    61 {
    62     //freopen("slikar.in","r",stdin);
    63     //freopen("slikar.out","w",stdout);
    64     memset(dis,127/3,sizeof(dis));
    65     memset(MP,127/3,sizeof(MP));
    66     scanf("%d%d",&n,&m);
    67     for(int i=1;i<=n;++i)
    68         for(int j=1;j<=m;++j)
    69             scanf(" %c",&mp[i][j]);
    70     for(int i=1;i<=n;++i)
    71         for(int j=1;j<=m;++j){
    72             if(mp[i][j]=='*') dfs(i,j,0);
    73             else{
    74                 switch(mp[i][j]){
    75                     case 'S':S=cal(i,j);break;
    76                     case 'D':T=cal(i,j);break;
    77                     case 'X':continue;break;
    78                 }
    79                 for(int k=0;k<4;++k){
    80                     int X=i+dx[k],Y=j+dy[k],t=1;
    81                     if(ok(X,Y)&&mp[X][Y]!='*'&&mp[X][Y]!='X') add(cal(i,j),cal(X,Y));
    82                 }
    83             }
    84         }
    85     if(!spfa()) puts("KAKTUS");
    86     else printf("%d
    ",dis[T]);
    87     return 0;
    88 }

    ————————今天好晚了懒得粘分割线呢————————

      芒果君:表示这次终于没有翻车,没有预计结果因为害怕这么多模拟写炸,最后还挺高的,开森,不过以后还是要多刷图论啊。

  • 相关阅读:
    BSGS模板(互质与不互质) 洛谷P4195、P3846
    整除分块(数论分块)
    洛谷P3327 [SDOI2015]约数个数和——莫比乌斯反演
    模块二
    模块
    二分法 匿名函数
    3.26作业
    函数的递归调用
    yield表达式 三元表达式
    3.25作业
  • 原文地址:https://www.cnblogs.com/12mango/p/7291966.html
Copyright © 2011-2022 走看看