2019.10.24模拟赛赛后总结

本文原创,如果有不到位的地方欢迎通过右下角的按钮私信我!

A.Icow Player

题目描述

被无止境的农活压榨得筋疲力尽后,Farmer John打算用他在MP3播放器市场新买的iCow来听些音乐,放松一下。FJ的iCow里存了N(1 <= N <= 1,000)首曲子,按1..N依次编号。至于曲子播放的顺序,则是按一个Farmer John自己设计的算法来决定:
* 第i首曲子有一个初始权值R_i(1 <= R_i <= 10,000)。
* 当一首曲子播放完毕,接下来播放的将是所有曲子中权值最大的那首(如果有两首或多首曲子的权值相同,那么这些曲子中编号最小的那首会被选中)。
* 一首曲子在播放结束后,它的权值会被平均地分给其他N-1首曲子,它本身的权值清零。
* 如果一首曲子的权值无法被平均分配(也就是说,无法被N-1整除),那么被N-1除的余数部分将会以1为单位,顺次分配给排名靠前的曲子(也就是说,顺序为曲目1、曲目2...依次下去。当然,刚播放过的那首曲子需要被跳过),直到多出的部分被分配完。
在选定的下一首曲子播放完毕后,这个算法再次被执行,调整曲子的权值,并选出再接下来播放的曲目。
请你计算一下,按FJ的算法,最先播放的T(1 <= T <= 1000)首曲子分别是哪些。

输入

第1行: 2个用空格隔开的整数:N 和 T
第2..N+1行: 第i+1行为1个整数:R_i

输出

第1..T行: 第i行为1个整数,表示iCow播放的第i首曲子

样例输入

3 4
10
8
11

样例输出

3
1
2
3

题目总结

这道题拿到之后最先想到的就是模拟,于是我大致把程序拆分成了个部分——输入、播放、分配和输出。其中输入就不再赘述,播放部分每次播放权值最大的一首,所以每次都要找到权值最大的一首歌。在这里我犯了一个非常严重的错误——对所有数据进行排序,而且我担心复杂度过高,于是以n为周期每n次播放排序一次,这也是我后面只得10分的原因。
错误部分代码:

    for(int i=1;i<=t;i++){
        if(i%n==1)sort(a+1,a+1+n,cmp);//每n次播放排序一次 
        if(i%n==0)cout<<a[n].bh<<endl;//防止出现n倍数次循环出现下标为零的情况 
        else cout<<a[i%n].bh<<endl;
        int sum1=a[i%n==0?n:i%n].r/n-1;//下面是分配部分代码 ,一堆玄学三目运算符 
        int sum2=a[i%n==0?n:i%n].r%n-1;
        for(int j=1;j<=n;j++){
            if(j==i%n==0?n:i%n)continue;
            a[j].r+=sum1;
        }
        s:;
        if(sum2>n){
            for(int j=1;j<=n;j++){
                if(j==i%n==0?n:i%n)continue;
                a[j].r++;
            }
            sum2-=n-1;
            goto s;
        }
        for(int j=1;j<=sum2;j++){
                if(j==i%n==0?n:i%n)continue;
                a[j].r++;
            }
    }

AC代码:

#include<bits/stdc++.h>
using namespace std;
struct node{
    int v;
    int d;
} a[1005];
//结构体方便比较权值大小,也方便查找数据的编号;
int main(){
    int n,t;
   int i,r,max,num,k,id;
   cin>>n>>t;
   for(i=1; i<=n; i++){
       cin>>a[i].v;
      a[i].d=i;
   }
   while(t--){
      max=0;
        for(i=1; i<=n; i++)  //比较权值的大小
          if(a[i].v>max){
             max=a[i].v;
            id=a[i].d;
         }
      cout<<id<<endl;//每次输出权值最大的歌曲的编号
      num=a[id].v;//分配部分
      k=num/(n-1); //平分播放了的歌曲的权值;
      r=num%(n-1);//除不尽小数部分化为整数1分给最近的歌曲权值;
      a[id].v=0;
      for(i=1; i<=n; i++){
          if(i!=id)a[i].v+=k;       
      }
      for(i=1; i<=r; i++){
         if(i==id)
             r++;
         else
            a[i].v+=1;
      }
    }
    return 0;
}

B.Costume

题目描述

万圣节又到了!Farmer John打算带他的奶牛去参加一个化装晚会,但是,FJ只做了一套能容下两头总长不超过S(1 <= S <= 1,000,000)的牛的恐怖服装。FJ养了N(2 <= N <= 20,000)头按1..N顺序编号的奶牛,编号为i的奶牛的长度为L_i(1 <= L_i <= 1,000,000)。如果两头奶牛的总长度不超过S,那么她们就能穿下这套服装。
FJ想知道,如果他想选择两头不同的奶牛来穿这套衣服,一共有多少种满足条件的方案。

输入

第1行: 2个用空格隔开的整数:N 和 S
第2..N+1行: 第i+1为1个整数:L_i

输出

第1行: 输出1个整数,表示FJ可选择的所有方案数。注意奶牛顺序不同的两种 方案是被视为相同的。

样例输入

4 6
3
5
2
1

样例输出

4

提示

【输出说明】 4种选择分别为:奶牛1和奶牛3;奶牛1和奶牛4;奶牛2和奶牛4;奶牛3和奶牛4。

题目总结

看大佬们的都是做的分治,但数据规模只有n<=20,000,所以直接暴力枚举所有可能然后判断可不可以装下就行了
AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,s,l[20001],ans;
int main(){
    freopen("costume.in","r",stdin);
    freopen("costume.out","w",stdout);
    cin>>n>>s;
    for(int i=1;i<=n;i++){
        cin>>l[i];
    }
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            if(l[i]+l[j]<=s)ans++;
        }
    }
    cout<<ans;
    return 0;
}

C.Contest

题目描述

FJ的N(1 <= N <= 100)头奶牛们最近参加了场程序设计竞赛:)。在赛场上,奶牛们按1..N依次编号。每头奶牛的编程能力不尽相同,并且没有哪两头奶牛的水平不相上下,也就是说,奶牛们的编程能力有明确的排名。
整个比赛被分成了若干轮,每一轮是两头指定编号的奶牛的对决。如果编号为A的奶牛的编程能力强于编号为B的奶牛(1 <= A <= N; 1 <= B <= N; A != B),那么她们的对决中,编号为A的奶牛总是能胜出。
FJ想知道奶牛们编程能力的具体排名,于是他找来了奶牛们所有M(1 <= M <= 4,500)轮比赛的结果,希望你能根据这些信息,推断出尽可能多的奶牛的编程能力排名。比赛结果保证不会自相矛盾。

输入

第1行: 2个用空格隔开的整数:N 和 M
第2..M+1行: 每行为2个用空格隔开的整数A、B,描述了参加某一轮比赛的奶牛的编号,以及结果(编号为A,即为每行的第一个数的奶牛为胜者)

输出

第1行: 输出1个整数,表示排名可以确定的奶牛的数目

样例输入

5 5
4 3
4 2
3 2
1 2
2 5

样例输出

2

提示

【输出说明】 编号为2的奶牛输给了编号为1、3、4的奶牛,也就是说她的水平比这3头奶 牛都差。而编号为5的奶牛又输在了她的手下,也就是说,她的水平比编号为5的 奶牛强一些。于是,编号为2的奶牛的排名必然为第4,编号为5的奶牛的水平必 然最差。其他3头奶牛的排名仍无法确定。

题目总结

这道题我直接全做错了然后卡了10分
我的错误思路是:如果有了a,b比赛的结果,就可以判断a,b的关系,如果一个人可以和其他n-1人的关系都确定,答案数就加一
错误代码:

#include<bits/stdc++.h>
using namespace std;
int win[101][101],n,m,a,b,ans,flag;
int main(){
    freopen("contest.in","r",stdin);
    freopen("contest.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        win[a][b]=win[b][a]=1;
    }
    for(int i=1;i<=n;i++){
        flag=0;
        for(int j=i+1;j<=n;j++){
            if(win[i][j]==0){
                flag=1;break;
            }
        }
        if(flag==0)ans++;
    }
    cout<<ans;
    return 0;
}

正确的做法是用Floyed,用一个二维数组存储比赛结果,然后三重循环枚举k、i、j,判断i==j?,然后判断win[i][k]是否为i,win[k][j]是否为k,如果全部满足的就把win[i][j]和win[j][i]设为i,最后判断是不是和其他人都比赛过了,如果是的话就答案数增加
AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
int a,b,n,m,f[101][101],ans;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        f[a][b]=1;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
              f[i][j]=f[i][j]|f[i][k]&f[k][j];
    for(int i=1;i<=n;i++){
        int gg=1;
        for(int j=1;j<=n;j++)
        if(i==j)continue;else 
         gg=gg&(f[i][j]|f[j][i]);
         ans+=gg;
    }
    printf("%d\n",ans);
}

D.Cowrun

题目描述

奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行N(1 <= N <= 10,000)分钟的晨跑。在每分钟的开始,贝茜会选择下一分钟是用来跑步还是休息。
贝茜的体力限制了她跑步的距离。更具体地,如果贝茜选择在第i分钟内跑步,她可以在这一分钟内跑D_i(1 <= D_i <= 1,000)米,并且她的疲劳度会增加1。不过,无论何时贝茜的疲劳度都不能超过M(1 <= M <= 500)。如果贝茜选择休息,那么她的疲劳度就会每分钟减少1,但她必须休息到疲劳度恢复到0为止。在疲劳度为0时休息的话,疲劳度不会再变动。晨跑开始时,贝茜的疲劳度为0。
还有,在N分钟的锻炼结束时,贝茜的疲劳度也必须恢复到0,否则她将没有足够的精力来对付这一整天中剩下的事情。
请你计算一下,贝茜最多能跑多少米。

输入

第1行: 2个用空格隔开的整数:N 和 M
第2..N+1行: 第i+1为1个整数:D_i

输出

第1行: 输出1个整数,表示在满足所有限制条件的情况下,贝茜能跑的最大距离

样例输入

5 2
5
3
4
2
10

样例输出

9

提示

【输出说明】 贝茜在第1分钟内选择跑步(跑了5米),在第2分钟内休息,在第3分钟内跑 步(跑了4米),剩余的时间都用来休息。因为在晨跑结束时贝茜的疲劳度必须 为0,所以她不能在第5分钟内选择跑步。

题目总结

这道题我根本就没看懂
AC代码:

#include<bits/stdc++.h>
#define MAXN 11111
#define MAXM 555
#define INF 1000000007
using namespace std;
int dp[MAXN][MAXM];
int a[MAXN];
int n, m;
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i++)
    {
        dp[i][0] = dp[i - 1][0];
        for(int j = 1; j <= m; j++)
        {
            if(i >= j) dp[i][0] = max(dp[i][0], dp[i - j][j]);
            dp[i][j] = max(dp[i - 1][j - 1] + a[i], dp[i][j]);
        }
    }
    printf("%d\n", dp[n][0]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/MikeC/p/11827800.html
今日推荐