首页 > 试题广场 >

游戏任务标记

[编程题]游戏任务标记
  • 热度指数:23495 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
游戏里面有很多各式各样的任务,其中有一种任务玩家只能做一次,这类任务一共有1024个,任务ID范围[1,1024]。请用32个unsigned int类型来记录着1024个任务是否已经完成。初始状态都是未完成。 输入两个参数,都是任务ID,需要设置第一个ID的任务为已经完成;并检查第二个ID的任务是否已经完成。 输出一个参数,如果第二个ID的任务已经完成输出1,如果未完成输出0。如果第一或第二个ID不在[1,1024]范围,则输出-1。

输入描述:
输入包括一行,两个整数表示任务ID.


输出描述:
输出是否完成
示例1

输入

1024 1024

输出

1

根据题意,输入的第一个游戏任务ID已被访问过,求解目的是确定第二个游戏任务ID是否被访问过。本身,不需要实现标记游戏ID被访问过的过程,因为题目只输入两个参数。题目中说所有游戏任务ID初始时均为未被访问状态,即在程序运行前,两个输入数字代表的游戏任务ID均未被访问。但是在程序运行时,可以默认第一个游戏任务ID已被访问过了,那么求解目标就转化成判断第二个输入值是否等于第一个输入值,只有相等时才表示第二个输入值被访问过了,否则未被访问过。由于题目设定了输入值的区间范围,所以在判断之前先要确定输入的两个数字是否均满足区间要求。若有至少一个不满足题设区间要求,则没有继续判断两个数值相等于否的必要,根据题意直接返回-1。如若两个输入数值均在题设区间范围内,方可判断其相等性:若相等,返回1;否则,返回0。

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        while (in.hasNext()) {
            int firstId = in.nextInt();
            int secondId = in.nextInt();

            System.out.println(isDone(firstId, secondId));
        }
    }

    private static int isDone(int firstId, int secondId) {
        //判断secondId是否被访问过
        //实则先判断firstId和secondId是否均满足[1, 1024]区间要求
        //其次,需要判断firstId和secondId代表的数值是否相等

        if (!inRange(firstId) || !inRange(secondId)) return -1;

        if (firstId == secondId) return 1;

        return 0;
    }

    private static boolean inRange(int num) {
        //判断num是否在[1, 1024]区间内

        return num >= 1 && num <= 1024;
    }
}
发表于 2022-01-25 09:28:30 回复(0)

思路是Bitmap
参考前面的大佬:哇卡哇卡,Real_Jump
他们写的很棒

代码中id1,id2之所以减1,我的理解是,防止越界.不减1,若id1等于1024,id1除以32等于32,但res数组长度是32,下标范围是0~31,所以不减一会越界.

import java.util.Scanner;
public class Main{
    static int[] res = new int[32];
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int id1 = scan.nextInt();
        int id2 = scan.nextInt();
        if(id1  1024 || id2  1024){
            System.out.println(-1);
            return;
        }
        int a = (id1 - 1) / 32;//id1处于第几个元素
        /*res[a]的十进制数是多少不重要,重要的是res的下标.把1~1024划分成32分,res的下标表示这32份.
        res数组是整形int数组,每一个元素是4个字节,即32位,用这32位表示32份中的一份,32*32=1024
        一个位的1或0,表示一个数的有无*/
        /*id1用res[a]这个数(二进制形式)的从右往左数第(id2-1)%32的位表示存在与否.
        要把这一位设为1,所以把1(二进制形式)最右边的那个1向左移动(id1-1)%32位,然后采用位运算'|',把那一位设为1.*/
        res[a] = res[a] | (1 << (id1-1)%32);
        int b = (id2 - 1) / 32;
        /*用二进制运算'&'判断res[b](二进制形式)从右往左数第(id2-1)%32的位是1还是0*/
        int tmp = res[b] & (1 << (id2-1)%32);
        if(tmp != 0){
            System.out.println(1);
        }else{
            System.out.println(0);
        }

    }
}
编辑于 2020-08-07 12:07:34 回复(0)
感觉用位图做是正解,32个int型刚好是128个字节,128*8 = 1024

import java.util.Scanner;

public class Main {

    private byte[] bytes = new byte[128];

    public int getValue(int n, int m) {
        if (n < 0 || n > 1023 || m < 0 || m > 1023) {
            return -1;
        }
        bytes[n/8] = (byte) (bytes[n/8] | 0b00000001 << (n%8));
        byte temp = bytes[m/8];
        if ((temp << (7-m%8)) >> m%8 == -1) {
            return 1;
        }
        return 0;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt()-1; int m = sc.nextInt()-1;
        Main t1 = new Main();
        System.out.println(t1.getValue(n, m));
    }
}
发表于 2020-08-01 22:24:52 回复(0)
题目的原意应该是让我们用bitmap的方式记住哪些任务被标记过了,但是由于牛客网的缺陷,每一次都是重新运行一次程序,导致记录功能实际上没法用。
如果用bitmap的方法来做的话,应该是这样的,如有问题还请指正
public class tencent_2 {
    public static void test(){
        try {
            BufferedReader br = new BufferedReader( new InputStreamReader( System.in));
            String[] input = br.readLine().trim().split(" ");
            int ID1 = Integer.valueOf(input[0]);
            int ID2 = Integer.valueOf(input[1]);
            int ans = solution(ID1, ID2);
            System.out.println(ans);
        }catch (Exception e){

        }
    }
    static int[] logs = new int[32];

    public static int solution(int ID1, int ID2){
        if(ID1<1 || ID1 > 1024 || ID2 < 1 || ID2 > 1024){
            return -1;
        }
        // 设置第一个任务已完成
        int logs_index = ID1>>5;
        int pos_i = ID1 & 31;
        int binary_pos = 1<<pos_i;
        logs[logs_index] = logs[logs_index] | binary_pos;

        // 查找第二个任务的状态
        logs_index = ID2>>5;
        pos_i = ID2 & 31;
        binary_pos = 1<<pos_i;
        int temp =logs[logs_index] & binary_pos;
        if(temp > 0){
            return 1;
        }else {
            return 0;
        }
    }
    
    public static void questions(){
        // 把5置为1,查询10的状态
        int ans_1 = solution(5,10);
        // 把10置为1,查询5的状态
        int ans_2 = solution(10,5);
        // ans_1 = 0,ans_2 = 1.
        // 说明已经成功的记录了标记过的任务
    }
}
这里的question方法相当于客户端的多次调用,把它放到真正的客户端里也可以,这里为了方便就直接在同一个class里了。

发表于 2019-08-22 17:23:29 回复(0)
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        int[] arr = new int[32];
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int id1 = sc.nextInt();
            int id2 = sc.nextInt();
            int result = result(id1, id2, arr);
            System.out.println(result);
        }
    }
    
    public static int result(int id1, int id2, int[] arr) {
        if (id1 < 1 || id1 > 1024 || id2 < 1 || id2 >  1024)
            return -1;
        
        // 分为32组,每组为一个unsigned int型数字,有32位,32*32 = 1024
        int zi = (id1 - 1) / 32;    // 组号
        int wi = (id1 - 1) % 32;    // 位号
        arr[zi] =  1 << wi;
        
        zi = (id2 - 1) / 32;
        wi = (id2 -1 ) % 32;
        if (arr[zi] == 1 << wi)
            return 1;
        else 
            return 0;
    }
}
1.unsigned int型为4字节,即32位,1024 / 32 = 32,所以建立一个长度为32的数组存放unsigned int型元素,每个数字有32位;
2.通过 / 和 % 求出 id1的 组号 和 位号;
3.通过对 1 进行向左移位操作,移位的次数和位号的数值相同,并赋值给对应的数组元素;
4.求出 id2 的组号 和 位号,判断其 组号 对应的数组元素的值 是否等于 1 向左位移 位号次数 后的值;
发表于 2018-10-14 21:57:49 回复(0)
public class Main {

    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        long[] arr=new long[32];
        int n = scan.nextInt();
        int m = scan.nextInt();
        if (n>1024||m>1024||n<=0||m<=0) {
            System.out.println("-1");
            return;
        }
        int p=(n-1)/32;
        int k=(n-1)%32;
        arr[p]=(long) (arr[p]+Math.pow(2, k));
        p=(m-1)/32;
        k=(m-1)%32;
        if ((arr[p]&(long)Math.pow(2, k))==(long)Math.pow(2, k)) {
            System.out.println(1);
        }else {
            System.out.println(0);
        }
    }
}

发表于 2018-10-02 16:36:07 回复(0)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[][] arr = new int[32][32];
        int num1 = scanner.nextInt() - 1;
        int num2 = scanner.nextInt() - 1;
        int row1 = num1 / 32;
        int column1 = num1 % 32;
        arr[row1][column1] = 1;

        int row2 = num2 / 32;
        int column2 = num2 % 32;
        if (num1 < 0 || num1 > 1023 || num2 < 0 || num2 > 1023) {
            System.out.println(-1);
        } else if (arr[row2][column2] == 1) {
            System.out.println(1);
        } else {
            System.out.println(0);
        }
    }
}


发表于 2018-08-09 21:34:26 回复(0)
//头一次发代码,略鸡冻
//话说那么多人直接几个if就提交了的是怎么想的,只是为了过case?
//题目中心要求是 将1024个任务的状态平均分给32unsigned int个变量,每个unsigned变量恰好有32位,每一位有0,1两种状态,
//所以32个unsigned int变量恰好可以表示一共1024个任务的状态,上码
import java.util.*;
public class Main {

	static long[] ar = new long[32]; //定义long型,但只用前32位,java没有unsigned int怪我喽
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			int change = sc.nextInt()-1;
			int find = sc.nextInt()-1;
			System.out.println(Find(change,find));
		}
	}
	public static int Find(int change,int find){
		if(change>=1024||find>=1024) return -1;
        
        //将1024个任务的状态平均分给32个变量,每个变量恰好可以表示32个任务(32位,一位一个),刚好满足题意
        
		int ch_b = change/32;    //计算要完成的任务在哪一个变量
		int ch_s = change-ch_b*32; //计算要完成的任务在该变量的哪一位
        
		int f_b = find/32;     //计算要查找的任务在哪一个变量
		int f_s = find-f_b*32;  //计算要查找的任务在该变量的哪一位
        
		ar[ch_b] = ar[ch_b]|(long)Math.pow(2, ch_s);  //通过或运算把表示要完成任务的那一位置为1
        
		if( (ar[f_b]|(long)Math.pow(2, f_s)) ==(long)Math.pow(2, f_s) ) //通过或运算来确定表示要查找的任务的那一位是否为1,long型问题同上
			return 1;
		else return 0;
	}
}

发表于 2017-09-03 18:29:49 回复(15)
这题目是真心服,如果不是看到通过率很高,我都不相信这题目有这么简单,不过话说这题目真的出的有点问题了,直接几个if条件语句就可以解决~~
import java.util.Scanner;

public class Main {
	
	
	//游戏任务标记
	public static void main(String[] args){
		
		Scanner in = new Scanner(System.in);
		
		int a = in.nextInt();
		int b = in.nextInt();
		
		if(a>1024 || a<1 || b>1024 || b<1) {
			System.out.println(-1);
		}
		else if(a != b){
			System.out.println(0);
		}
		else{
			System.out.println(1);
		}
	}
	
}

发表于 2017-08-31 11:06:12 回复(4)

这个题目应该考的是通过位来检查任务是否完成,但因为例子只给一次,所以每次都只用判断所给的两个值就行,数组都用不上,,,,题目出的不好,自己懒省事也就跟着这样做了^_^
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner console = new Scanner(System.in);
        int[] id = new int[32];
        int id1 = console.nextInt();
        int id2 = console.nextInt();
        if(id1 < 1 || id2 < 1 || id1 > 1024 || id2 > 1024){
            System.out.println(-1);
            return;
        }
        if(id1 == id2){
            System.out.println(1);
            return;
        } else {
            System.out.println(0);
            return;
        }
    }
}
发表于 2017-08-18 10:56:02 回复(0)