专题枚举模拟与排序

Posted Johnny*

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了专题枚举模拟与排序相关的知识,希望对你有一定的参考价值。

专题(四)枚举、模拟与排序

特别数的和

【题目描述】
在这里插入图片描述AcWing 1245. 特别数的和

【思路】
位数分解

import java.util.Scanner;
public class Main{
    public static boolean check(int x){
    	//分解位数
        while(x > 0){
            int t = x % 10;
            //判断是否满足条件
            if( t == 2|| t == 0|| t == 1 || t== 9) return true;
            x /= 10;
        }
        return false;
    }
    public static void main(String args[]){
        Scanner reader = new Scanner(System.in);
        int n = reader.nextInt();
        long ans = 0;
        //枚举
        for(int i = 1; i <= n ; i++){
            if(check(i))
                ans += i;
        }
        System.out.println(ans);
    }
}

错误票据

在这里插入图片描述
在这里插入图片描述

AcWing 1204. 错误票据

【思路】

开一个数组cnt统计 各个数出现的次数
易知:因为重号不为最大和最小数,所以若i为重号则i次数为0,cnt[i - 1]必不为0

import java.io.*;
public class Main{
    static int N = 100010;
    static int cnt [] = new int [N];
    public static void main(String args[]) throws Exception{
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        
        int n = Integer.parseInt(bf.readLine());
        while(n -- > 0){
            String s [] = bf.readLine().split("\\\\s+");//表示若干个空格
            for(int i = 0; i < s.length; i ++)
                cnt[ Integer.parseInt(s[i]) ]++;
        }
            
        //断号不可能发生在最大和最小号
        // 0 1 1 1 0 1 0
        int a = 1;
        for(int i = 1; i < 100000; i ++){
            if( cnt[i] == 0 && cnt[i - 1]!=0 ) {
                a = i;
                break;
            }
        }
        int b = 3;
        for(int i = 0; i < 100000; i ++)
            if( cnt[i] > 1){
                b = i;
                break;
            }
        System.out.println(a+ " "+ b);
    }
}

外卖店优先级

【思路】
状态压缩

st[i] 表示id号为i的店铺当前是否在优先队列中
score[i]   表示id号为 i的店铺当前的优先级
last[i]   表示id号为i的店铺上一次有订单的时刻

1、 将所有订单信息按(时间,店铺id)升序排序
2、 枚举所有订单,获得该店的所有订单q[i ~ j]
 			t时刻该店(id)有订单,订单数为 cnt = 
 			处理t时刻前店铺的订单信息:
 					score[id] - = t -last[id] - 1;
 					if(score[id] < 0) score[id] = 0;
 					if(score[id] <= 3) st[id] =false;
 					last[id] = t;

 			处理t时刻该店铺有订单:
 					score[id] += cnt *2
 					if(score[id] >5) st[id] = true
			
			if(t < T){//最后一段时间没有订单
				score[id] -= T - last[id];
			}
			if(score[id] <= 3) st[id] = false;

import java.io.*;
import java.util.Arrays;
class order implements Comparable<order>{
    int ts, id;
    public order(int t, int i){
        this.ts = t;
        this.id = i;
    }
    //自定义排序:先按时间排序、再按id排序
    public int compareTo(order o){
        if(this.ts == o.ts) return this.id - o.id;//若时间相同则按店铺id升序排序
        else return this.ts -o.ts;  //按时间升序排序
    }
    public String toString(){
        return this.ts+ " "+ this.id +"\\n";
    }
}
public class Main{

    static int  N = 100010;
    static order []q = new order[N];
    static int [] score = new int[N]; //score[i]表示id号为i的店当前优先级
    static int []last = new int[N]; //last[i]表示id号为i的店最近一次有订单的时刻
    static boolean [] st = new boolean[N]; //st[i]表示id号为i的店当前在不在优先级队列中
    public static void main(String agrs[]) throws Exception{
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String s[] = bf.readLine().split(" ");
        int n = Integer.parseInt(s[0]),m = Integer.parseInt(s[1]), T = Integer.parseInt(s[2]);
        for(int i = 0; i < m; i ++){
            String str[] = bf.readLine().split(" ");
            q[i] = new order(Integer.parseInt(str[0]), Integer.parseInt(str[1]));
        }
        Arrays.sort(q,0, m );
        
       System.out.println(Arrays.toString(q));
        for(int i = 0; i  < m; ){
            int j = i;
            while(j < m && q[j]== q[i]) j ++;  // 相同(ts、id皆相同)订单
            int  t = q[i].ts, id = q[i].id, cnt = j - i;
            i = j;
            
            //处理一批相同的订单
            score[id] = score[id] - t - last[id] - 1;//处理t时刻前订单,有(t -last[id]-1)个时刻没有订单
            if(score[id] < 0) score[id] = 0;
            if(score[id] <= 3) st[id] = false;
            
            score[id] += cnt *2;   //处理t时刻订单
            if(score[id] > 5) st[id] = true;
            
            last[id] = t;
            
            //处理下一批订单
            
            
        }
        //最后一段没有订单
        for(int i = 1; i <= n; i ++){
            if(last[i] < T){
                score[i] = score[i] - T - last[i];
                if(score[i] <= 3) st[i] = false;
            }
        }
        int ans = 0;
        for(int i = 1; i <= n; i ++)
            if(st[i]) ans++;
        System.out.println(ans);
    }
    
}

【题目描述】
在这里插入图片描述

【思路】
做完才发现其实可以预处理 都减去1 哭了
一堆边界判断

import java.util.Scanner;
import java.lang.Math;
class Main{
    
    public static int get_y(int row, int w, int x){
        //根据规律 行数为偶数则从左到右递增
        int y = 0;
        if( (row & 1) == 0 ) y = (x % w == 0? w:x % w);
        else y = w - x % w + 1;
        return y;
    }
        
    public static void main(String args[]){
        
      
        Scanner reader = new Scanner(System.in);
        int w = reader.nextInt(), m = reader.nextInt(), n = reader.nextInt();
        //注意处理边界
        //计算两个数的位置
        int x1 = m / w + (m % w == 0? -1: 0), x2 = n / w + (n % w == 0? -1: 0);
        int y1 = get_y(x1, w, m), y2 = get_y(x2, w, n);
        
        //System.out.println(x1+" "+y1);
        //System.out.println(x2+" "+y2);
        //计算移动距离
        int res = Math.abs(x1 - x2) + Math.abs(y1 - y2);
        System.out.println(res);
        
    }
}

以上是关于专题枚举模拟与排序的主要内容,如果未能解决你的问题,请参考以下文章

模拟/枚举专题

枚举算法Day120170529-2枚举算法专题练习

枚举算法Day120170529-2枚举算法专题练习 题解

后缀排序

[M排序] lc274. H 指数(排序+模拟)

POJ - 1054 The Troublesome Frog 模拟 枚举优化。