牛客IOI周赛18-普及组 比赛总结

题目A

数字计数
给出n个数字,请你求出在给出的这n个数字当中,最大的数字与次大的数字之差,最大的数字与次小的数字之差,次大的数字与次小的数字之差,次大的数字与最小的数字之差.

对于%30%的数据,保证n \leq 8n≤8

对于%60%的数据,保证n\leq 16n≤16

对于%100%的数据,保证n\leq100n≤100

对于所有数据,保证每个数字小于等于100且不同数字的个数大于4

思路

签到题,注意去重就好了。

代码

import java.util.*;
public class Main{
    public static void main(String args[])
    {
        Scanner reader=new Scanner(System.in);
        int n=reader.nextInt();
        int array[]=new int[n];
        for(int i=0;i<n;++i)
            array[i]=reader.nextInt();
        Arrays.sort(array);

        int max=array[n-1];
        int min=array[0];
        int second_min=0;
        int second_max=0;
        for(int i=1;i<n;++i)
        {
            if(array[i]!=min)
            {
                second_min=array[i];
                break;
            }
        }

        for(int i=n-2;i>=0;--i)
        {
            if(array[i]!=max)
            {
                second_max=array[i];
                break;
            }
        }
        System.out.println((max-second_max)+" "+(max-second_min)+" "+(second_max-second_min)+" "+(second_max-min));
    }
}

结果

A了,简单题,没什么好总结的

题目B

MoveToEx找到了很多不同颜色的珠子,他把这些珠子排成了一列,每个珠子的颜色用1,2…表示.定义一个区间的美观度为区间中不同颜色的珠子个数现在MoveToEx想知道,在所有n * (n+1)/2个区间中,所有区间的美观度之和是多少.

思路

我们可以知道,假设下标从1开始,那么从1到3的不同颜色珠子的个数是以从1到2的不同颜色珠子的个数为基础的。我们可以利用一个标记数组,来找出一行的不同珠子的情况,并存放在dp数组中,dp数组的含义就是当前的位置i截取到位置j的长度的不同珠子的个数。

代码

import java.util.Scanner;

public  class Main{
    public static void  main(String args[]){
        Scanner reader=new Scanner(System.in);
        int n=reader.nextInt();

        //存放各个数字
        int nums[]=new int[1200];
        for (int i=1;i<=n;++i)
            nums[i]=reader.nextInt();

        //动态数组
        int dp[][]=new int[1200][1200];

        //对角线上的数值都是1
        for (int i=1;i<=n;++i)
            dp[i][i]=1;

        int visited[]=new int[1200];
        for (int i=1;i<=n;++i)
        {
            visited[nums[i]]=1;//在当前这个以位置i起始的地方,所有出现过得数字,就标记为1
            for (int j=i+1;j<=n;++j)
            {
                if (visited[nums[j]]==0)
                {
                    dp[i][j]=dp[i][j-1]+1;
                    visited[nums[j]]=1;
                }
                else
                {
                    dp[i][j]=dp[i][j-1];
                }
            }

            for (int g=0;g<1200;++g)//初始化标记
                visited[g]=0;
        }

        int count=0;//计算总数
        for(int i=1;i<=n;++i)
        {
            for (int j=i;j<=n;++j)
                count+=dp[i][j];
        }
        System.out.println(count);
    }
}

总结

也是简单题,就是把当前位置为起始的看做是一个,然后,拓展为二维数组那样来计算。最后,只需要计算一个上三角形即可。也不算难题。

题目C

智斗恶龙
链接:https://ac.nowcoder.com/acm/contest/7226/C
来源:牛客网

MoveToEx来到了一个异次元世界,在这个世界中存在着恶龙.作为拯救世界的勇士,MoveToEx要打倒恶龙.
为了寻找能打倒恶龙的能力,MoveToEx来到了一个地宫中.MoveToEx在刚到达地宫时,他因为传送魔法的原因,被传送到了(sx,sy)的位置,而由于这个地宫中特有的封印值d,MoveToEx只能到达那些他需要走小于等于d步就能到达的格子.在这个地宫中的某些格子中存在着一些宝藏,当MoveToEx来到这些存在宝藏的格子上时,他可以获得这些格子上的宝藏,当然他也可以选择不获取这些格子上的宝藏.每个宝藏有其特殊的能力值.为了打败恶龙,MoveToEx至少需要x种不同能力的宝藏,但是由于MoveToEx的身体无法承受太强烈的能量差距,所以他希望他所使用的宝藏的最大与最小的能力值之差最小.
当然,地宫中有一些陷阱,MoveToEx在地宫中时不能经过这些陷阱.
所以请你帮助MoveToEx计算一下,MoveToEx所使用宝藏的最大与最小的能力值之差.

思路

先进行广搜,搜到所有已当前位置可以拓展到的点,把他们的能量都加入到集合中【因为打败恶龙要使用不同的能力值,所以要进行去重】,再把数据从集合【自动去重】的数据存放到数组中,进行排序,并且每次取出相应的个数的首尾两个数值进行相减,枚举一遍,得到最小值即可。

代码

import java.util.*;

class Point{
    int x; //横坐标
    int y; //纵坐标
    int step;//到达该店所需要的步数
}

public class Main{
    static int n;
    static int m;
    static int sx;
    static int sy;
    static int d;
    static int x;
    static long map[][]=new long[1005][1005];//地图
    static int visited[][]=new int[1005][1005];//标记数组
    static Queue<Point> queue=new LinkedList();
    static HashSet<Long> set=new HashSet();

    //右下左上
    static int d_x[]={0,1,0,-1};
    static int d_y[]={1,0,-1,0};

    public static void main(String[] args) {
        Scanner reader=new Scanner(System.in);
        int T=reader.nextInt();//T组测试数据
        for (int g=0;g<T;++g)
        {
            n=reader.nextInt();//行数
            m=reader.nextInt();//列数
            sx=reader.nextInt();//出发初始横坐标
            sy=reader.nextInt();//出发初始列坐标
            d=reader.nextInt();//限制走的步数
            x=reader.nextInt();//打败恶龙所需要的宝藏数目

            for (int i=1;i<=n;++i)
            {
                for (int j=1;j<=m;++j)
                {
                    map[i][j]=reader.nextLong();//接受地图
                    visited[i][j]=0;//初始化标记数组
                }
            }
            queue.clear();//初始化队列
            set.clear();//清空集合

            if (map[sx][sy]==-1)
            {
                System.out.println("no");
                continue;
            }

            Point temp=new Point();
            temp.x=sx;
            temp.y=sy;
            temp.step=0;
            visited[sx][sy]=1;//已经访问
            queue.offer(temp);

            while (!queue.isEmpty())
            {
                int a_x=queue.peek().x;
                int a_y=queue.peek().y;
                int step=queue.peek().step;

                //大于0才加入
                if (map[a_x][a_y]>0)
                    set.add(map[a_x][a_y]);

                for (int i=0;i<=3;++i)
                {
                    int temp_x=a_x+d_x[i];
                    int temp_y=a_y+d_y[i];
                    int temp_steps=step+1;
                    if (check(temp_x,temp_y,temp_steps))
                    {
                        Point temporary=new Point();
                        temporary.x=temp_x;
                        temporary.y=temp_y;
                        temporary.step=temp_steps;
                        visited[temp_x][temp_y]=1;
                        queue.offer(temporary);
                    }
                }
                queue.poll();
            }

            int length=set.size();
             long result[]=new long[length];
            Iterator it=set.iterator();
            int index=0;

            while (it.hasNext())
            {
                result[index++]=(long)it.next();
            }
            Arrays.sort(result);


            long min=Long.MAX_VALUE;
            if (length<x)
                System.out.println("no");
            else
            {
                for (int i=0;i+x-1<length;++i)
                {
                    long k= result[i+x-1]-result[i];
                    if (k<min)
                        min=k;
                }
                System.out.println(min);
            }
        }
    }
    public static boolean check(int a,int b,int steps)
    {
        return a>0 && a<=n && b>0 && b<=m && visited[a][b]==0 && map[a][b]>=0 && steps<=d;
    }
}

结果

ac了,有两个坑点,
一个是,如果起始位置是一个陷阱,那么就没有搜索的必要的,直接输出no即可;
另外一个坑点是,数据是比int类型大的,要使用long类型才不会溢出。
以后,尽量都使用long,避免因为这个而导致wa。

第四道题,没做出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值