首页 > 试题广场 >

小美的书架

[编程题]小美的书架
  • 热度指数:4787 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

小美的书架上有很多书。小美是个爱读书的新时代好青年。

小团虽然也喜欢看书,但小团大多数时候都更喜欢来小美家蹭书读。

这就导致小美的书架上很多书都会被小团借走。

小美很烦这一点,就想出了一个招数,小美的书架是一行一行的,他会对一些行加锁,这样小团就借不走了。

现在小团想要借书,请你帮忙看看小团能不能借到书,如果可以借到的话在哪一行书架上有这本书。

为了简单起见,每本书将用一个正整数进行编号,小美的书架一共有N行。


输入描述:

第一行两个正整数N,M,Q,表示小美书架有N行编号1到N,书本编号从1到M,接下来有Q个操作

接下来Q行,每行是下列操作中的一种:

1 x y : x是书本的编号,y是书架的行编号,代表小美将编号为x的书本放置到y行上。若该书本在小团手上则放置无效,若原来该书在书架上且原行上锁则放置无效,若该书被放置到一个锁了的行上则放置无效。

2 y : y是书架的行编号,代表小美将行编号为y的书架加锁,对已经上锁的书架行该操作无效。

3 y : y是书架的行编号,代表小美将行编号为y的书架锁去掉,对无锁的书架行该操作无效。

4 x : x是书本的编号,代表小团想借编号为x的书本,对该操作若可以借到输出一行正整数在哪一行,借不到输出一行-1

5 x : x是书本的编号,代表小团还回来编号为x的书本。若该书本不在小团手上该操作无效。



输出描述:

对于每个操作4,若可以借到输出一行正整数在哪一行,借不到输出一行-1

示例1

输入

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

输出

4
-1
-1
3

备注:

对于30%的数据有

对于80%的数据有

对于100%的数据有

思路

  • books[]数组,用不同的值记录每本书的状态
  • bookshelf[]数组记录书架是否上锁
    然后根据不同的情况模拟即可

注意:题目有误,应该n为书编号,m为书架编号

import java.util.*;
import java.lang.*;
import java.io.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        // 书编号
        int n = sc.nextInt();
        // 书架编号
        int m = sc.nextInt();
        // books[i]代表的状态
        // -1:借不到,行上锁/未被放到书架上/已借走
        // 0:小团借走了
        // 1-n:在编号为1-n的书架上
        int[] books = new int[n+1];
        // 初始时所有书未放到书架上,不能借
        Arrays.fill(books,-1);
        // false:未上锁    true:上锁
        boolean[] bookshelf = new boolean[m+1];
        int q = sc.nextInt();
        while(q-->0){
            int option = sc.nextInt();
            int x,y;
            switch(option){
                case 1:
                    x = sc.nextInt();
                    y = sc.nextInt();
                    // 不能放的情况,什么都不做
                    if(books[x]==0 || (books[x]>0&&bookshelf[books[x]]) || bookshelf[y]){
                        break;
                    }else{
                        books[x] = y;
                    }
                    break;
                case 2:
                    y = sc.nextInt();
                    bookshelf[y] = true;
                    break;
                case 3:
                    y = sc.nextInt();
                    bookshelf[y] = false;
                    break;
                case 4:
                    x = sc.nextInt();
                    if(books[x]>0 && !bookshelf[books[x]]){
                        System.out.println(books[x]);
                        // 被小团借走了
                        books[x] = 0;
                    }else{
                        System.out.println(-1);
                    }
                    break;
                case 5:
                    x = sc.nextInt();
                    if(books[x]==0){
                        books[x] = -1;
                    }
                    break;
                default:break;
            }
        }
    }
}
发表于 2022-03-02 15:05:04 回复(0)
卡30%  卡得人都傻了....
发表于 2021-03-26 22:12:01 回复(12)
这个题目不知道大家有没有觉得有歧义,明明先输入N为书架,M为书本,结果设置书架是否上锁的boolean数组的时候大小需要设成M,
发表于 2021-03-10 15:40:55 回复(6)
这题真是垃圾,请问你有M本书,这些书总该都放在书架上吧,结果题目不说书籍放置情况,还书,还回来的书也应该要放到某个地方吧,什么垃圾题目,歧义一大堆
发表于 2021-09-11 13:08:47 回复(2)
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<set>
using namespace std;
struct C_book//构建书架的结构信息
{
   int lock;
   set<int>book;
}a[10000];
struct Book//构建书的结构信息
{
    int who;
    int row;
}b[10000];
int main()
{
    int n,m,q;
    cin>>n>>m>>q;
    while(q--)//进行操作模拟
    {
        int choose,x,y;
        cin>>choose;
        if(choose==1)
        {
            cin>>x>>y;
            if(b[x].who||a[b[x].row].lock||a[y].lock) continue;
            a[y].book.insert(x);
            b[x].row=y;
        }
        else if(choose==2)
        {
            cin>>y;
            a[y].lock=1;
        }
        else if(choose==3)
        {
            cin>>y;
            a[y].lock=0;
        }
        else if(choose==4)
        {
            cin>>x;
            //printf("x=%d row=%d\n",x,b[x].row);
            if(b[x].who||a[b[x].row].lock||b[x].row==0) cout<<-1<<endl;
            else
            {
                cout<<b[x].row<<endl;
                b[x].who=1;
                b[x].row=0;
                a[b[x].row].book.erase(x);
            }
        }
        else
        {
            cin>>x;
            if(b[x].who==0) continue;
            b[x].who=0;
            b[x].row=0;
        }
    }
    return 0;
}


发表于 2021-04-03 19:52:49 回复(0)
第一行两个正整数N,M,Q,表示小美书架有N行编号1到N书本编号从1到M
这里 题目描述有误,根据一直通不过的测试用例 来看。
321 814 15512
3 691
1 260 338
3 : 解锁 ,操作的应该是 行, 1 后面对应的分别是 书号和行号。 691 和 338 都大于 321,所以,第一个数字 N 应该为 书本编号,第二个数字 M 应为 行号。
import java.util.*;
import java.io.*;
 
public class Main {
    public static void main(String[] agrs) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = "";
        while((s = br.readLine()) != null) {
            String[] sc = s.split(" ");
            int m = Integer.parseInt(sc[0]);
            int n = Integer.parseInt(sc[1]);
            int q = Integer.parseInt(sc[2]);
            int[] lock = new int[n + 1];
            Map<Integer, Integer> map = new HashMap<>();
            Set<Integer> set = new HashSet<>();
            for(int i = 0; i < q; i ++) {
                sc = br.readLine().split(" ");
                int a = Integer.parseInt(sc[1]);
                if(Integer.parseInt(sc[0]) == 1) {
                    if(a <= 0 || a > m) {
                        continue;
                    }
                    int b = Integer.parseInt(sc[2]);
                    if(b > n || b <= 0) {
                        continue;
                    }
                    int c = 0;
                    if(map.containsKey(a)) {
                        c = map.get(a);
                    }
                    if(lock[b] == 1 || lock[c] == 1) {
                        continue;
                    }
                    if(set.contains(a)) {
                        continue;
                    }
                    map.put(a, b);
                } else if (Integer.parseInt(sc[0]) == 2) {
                    if(a <= 0 || a > n) {
                        continue;
                    }
                    lock[a] = 1;
                } else if (Integer.parseInt(sc[0]) == 3) {
                    if(a <= 0 || a > n) {
                        continue;
                    }
                    lock[a] = 0;
                } else if (Integer.parseInt(sc[0]) == 4) {
                    if(a <= 0 || a > m) {
                        System.out.println(-1);
                        continue;
                    }
                    int b = map.getOrDefault(a, 0);
                    if(b == 0 || lock[b] == 1) {
                        System.out.println(-1);
                    } else {
                        map.remove(a);
                        set.add(a);
                        System.out.println(b);
                    }
                } else {
                    if(set.contains(a)) {
                        set.remove(a);
                    }
                }
            }
        }
    }
}


编辑于 2021-03-28 15:21:29 回复(1)
思路很简单,直接模拟借书、还书、对书架加锁和解锁的过程即可
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] params = br.readLine().trim().split(" ");
        int n = Integer.parseInt(params[0]);
        int m = Integer.parseInt(params[1]);
        int q = Integer.parseInt(params[2]);
        int op, x, y;
        boolean[] locked = new boolean[10001];    // 表示第i行书架是否被上锁
        boolean[] hasBook = new boolean[10001];   // 表示第i本书是否在小团手上
        // 记录第i本书在第j行书架上
        int[] pos = new int[10001];
        for(int i = 0; i < q; i++){
            params = br.readLine().trim().split(" ");
            if(params.length == 3){
                op = Integer.parseInt(params[0]);
                x = Integer.parseInt(params[1]);
                y = Integer.parseInt(params[2]);
                // 书架在小团手上,操作无效
                if(hasBook[x]) continue;
                // 这行书架被锁了,操作无效
                if(locked[y]) continue;
                // 如果这本书在一行上了锁的书架上,操作无效
                if(pos[x] != 0 && locked[pos[x]]) continue;
                // 否则将x放在第y行书架上
                pos[x] = y;
            }else{
                op = Integer.parseInt(params[0]);
                if(op == 2){
                    // 直接加锁
                    y = Integer.parseInt(params[1]);
                    locked[y] = true;
                }else if(op == 3){
                    // 直接去掉锁
                    y = Integer.parseInt(params[1]);
                    locked[y] = false;
                }else if(op == 4){
                    x = Integer.parseInt(params[1]);
                    // 如果x已经放在了书架上,且该层书架又没上锁,就直接输出
                    if(pos[x] != 0 && !locked[pos[x]]){
                        System.out.println(pos[x]);
                        pos[x] = 0;
                        hasBook[x] = true;
                    }else
                        System.out.println(-1);
                }else{
                    x = Integer.parseInt(params[1]);
                    // 这本书不在小团手上,操作无效
                    if(!hasBook[x]) continue;
                    // 否则直接令小团失去这本书
                    hasBook[x] = false;
                }
            }
        }
    }
}


发表于 2021-03-05 23:56:38 回复(4)
气死了 什么垃圾题目 
发表于 2022-03-10 15:20:10 回复(0)

什么 SB 题目,数据m, n 输入给反了。

维护三个信息:

  1. 使用集合tuan维护小团手上有的书
  2. 使用哈希表shelf维护书架上的书所属行
  3. 使用哈希表(布尔数组shelfLock实现)维护书架上的行是否被锁

操作1:将书x放入书架第y行,只有 不在团+尚未放入书架或者放入书架行未被锁+新的书架行没锁 才合法。

操作2:锁上书架y,管你之前是否上锁,统统锁上shelfLock[y] = True

操作3:锁上书架y,管你之前是否上锁,统统解锁shelfLock[y] = False

操作4:团来借 y 书,题目很坑,没说 y 书必须在书架上才能借(艹)。只有 该书不在团手里+该书必须在书架上且没上锁 才能外接。外接之后需要将该书从书架上删除shelf.pop(y)+小团借走tuan.add(y)

操作5:团来还 y 书,团只有借了这本书才归还,且不是放到到原书架上第n行,直接甩小美脸上就行,因此tuan.remove(y)

m, n, q = map(int, input().split())
tuan = set()
shelf, shelfLock = {}, [False] * (n + 1)
for _ in range(q):
    operate, *other = map(int, input().split())
    # 将书x放入书架第y行
    if 1 == operate:
        x, y = other
        # 不在团+尚未放入书架或者放入书架行未被锁+新书架行没锁
        if x not in tuan and (x not in shelf or not shelfLock[shelf[x]]) and not shelfLock[y]:
            shelf[x] = y
    # 锁上书架y
    elif 2 == operate:
        shelfLock[other[0]] = True
    # 解锁书架y
    elif 3 == operate:
        shelfLock[other[0]] = False
    # 团来借书
    elif 4 == operate:
        if other[0] not in tuan and other[0] in shelf and not shelfLock[shelf[other[0]]]:
            print(shelf[other[0]])
            shelf.pop(other[0])
            tuan.add(other[0])
        else:
            print(-1)
    else:
        if other[0] in tuan:
            tuan.remove(other[0])
发表于 2021-08-16 21:02:37 回复(0)
很无语,书架就321行,你要无去338行放260书,怎么不超范围啊。。。脑残。。


发表于 2022-05-24 15:55:22 回复(0)
疯狂卡数据,但是数组越界,把多余行和书编号的数据不管,输出结果又不对;最后通过的方法是将书的大小和书架行数的大小都设置为给定数据的最大值,然后全部通过了。
注意:给的测试数据里,根本和第一行给的书数量和书架行数量有所冲突。
发表于 2021-07-07 12:14:25 回复(0)
package main

import (
	"fmt"
)

func main() {
	n, m, q, x, y := 0, 0, 0, 0, 0
	lock := make(map[int]bool, 0)
	shell := make(map[int]int, 0)
	has := make(map[int]bool, 0) //小团手里有的书
	fmt.Scanf("%d %d %d", &m, &n, &q)
	for q > 0 {
		q--
		t := 0
		fmt.Scanf("%d", &t)
		switch t {
		case 1:
			fmt.Scanf("%d %d", &x, &y)
			// 在小团手里或者y行上锁了
			if has[x] || lock[y] {
				continue
			}
            // 原本在的行上锁了
			if shell[x] != 0 && lock[shell[x]] {
				continue
			}
			shell[x] = y
		case 2:
			fmt.Scanf("%d", &y)
			lock[y] = true
		case 3:
			fmt.Scanf("%d", &y)
			lock[y] = false
		case 4:
			fmt.Scanf("%d", &x)
			if v, ok := shell[x]; ok && !lock[shell[x]] {
				delete(shell, x)
				has[x] = true
				fmt.Println(v)
			} else {
				fmt.Println(-1)
			}
		case 5:
			fmt.Scanf("%d", &x)
			if has[x] { //还书不是直接放书架上,是给小妹
				has[x] = false
			}
		}

	}
}

这题目描述我真吐血,还书不是原样返回是给小美
发表于 2023-08-05 15:52:50 回复(0)
我之前想多了,还以为拿完书会再放回去。。。
from collections import defaultdict
n, m, q = map(lambda x: int(x), input().split())

des_lock = [False]*(m+1)
book_des = {}
tuan = set()

for _ in range(q):
    x, y = None, None
    data = list(map(lambda x: int(x), input().split()))

    if data[0]==1: # 编号为3
        x, y = data[1], data[2]
        if x in tuan&nbs***bsp;des_lock[y]: # 书在小团手中或书架被上锁
            continue
        
        if x in book_des and des_lock[book_des[x]]:
            continue

        book_des[x] = y

    if data[0]==2:
        des_lock[data[1]] = True
    if data[0]==3:
        des_lock[data[1]] = False
    
    if data[0]==4:
        x = data[1]
        if x in book_des and not des_lock[book_des[x]]: # 在书架上且没加锁
            tuan.add(x)
            print(book_des[x])
            book_des.pop(x)
        else:
            print(-1)

    if data[0]==5:
        x = data[1]
        if x not in tuan:
            continue
        tuan.remove(x)


发表于 2022-09-16 02:13:37 回复(0)
这个题第三个例子有问题啊,检查完发现第一次插入211号书(556条指令)时,是插在48行,第34次获取书的时候获取的就是211号书,第34次小团拿书的指令是第146条指令,他那里能拿到书啊,还是在461行拿到的书,书架行数才321行

发表于 2022-08-06 20:56:18 回复(3)
不要忘记还回去了 同时还回去是不放回书架
import java.util.HashMap;
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        HashMap<Integer, Integer> lock = new HashMap<>();
        HashMap<Integer, Integer> book = new HashMap<>();
        HashMap<Integer, Integer> brrowr = new HashMap<>();
     
        String[] str;
        str = br.readLine().split(" ");
        int n = Integer.parseInt(str[0]);
        int m = Integer.parseInt(str[1]);
        int q = Integer.parseInt(str[2]);
        ArrayList<Integer> ret = new ArrayList<Integer>();
        for(int i = 0; i < q; i++){
            str = br.readLine().split(" ");
            if(str[0].equals("1")){
                int a = Integer.parseInt(str[1]);
                int b = Integer.parseInt(str[2]);
                if(!brrowr.containsKey(a) && !lock.containsKey(b)){
                    if(book.containsKey(a) && lock.containsKey(book.get(a))){
                        continue;
                    }
                    book.put(a, b);
                }
    
            }else if (str[0].equals("2")) {
                int loc = Integer.parseInt(str[1]);
                lock.put(loc, 1); // 表示对第loc行上锁
            }else if (str[0].equals("3")) { //移除第loc行锁
                int loc = Integer.parseInt(str[1]);
                if(lock.containsKey(loc)){
                    lock.remove(loc);
                }
            }else if (str[0].equals("4")) {
                int bn = Integer.parseInt(str[1]);
                int line;
                if(book.containsKey(bn) && !lock.containsKey(line = book.get(bn))){
                    book.remove(bn);
                    brrowr.put(bn, 1);
                    ret.add(line);
                }else{// 未上锁
                    ret.add(-1);
                }
            }else{
                int bn = Integer.parseInt(str[1]);
                if(!brrowr.containsKey(bn)){
                    continue;
                }else{
                    brrowr.remove(bn);
                }
            }
        }
        for(int i = 0; i < ret.size(); i++){
            bw.write(Integer.toString(ret.get(i)));
            bw.newLine();
            bw.flush();
        }
    }
}


编辑于 2022-03-31 22:27:20 回复(0)
兄弟们,题是不是错了,书架是不是得不设上限???
发表于 2022-03-10 23:39:03 回复(0)
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
int main(){
    int n,m,Q;
    cin>>n>>m>>Q;
    unordered_map<int,int> bookind;
    unordered_map<int,bool> islocked;
    for(int i=1;i<=m;i++)
        bookind[i]=0;
    for(int i=0;i<=n;i++)
        islocked[i]=false;
    while(Q--){
        int opr;
        cin>>opr;
        if(opr==1){
            int book,line;
            cin>>book>>line;
            if(!islocked[line]&&bookind[book]!=-1)
                if(bookind[book]>=0&&!islocked[bookind[book]])
                    bookind[book]=line;
        }
        else {
            int tmp;
            cin>>tmp;
            if(opr==2){
                islocked[tmp]=true;
            }
            if(opr==3){
                islocked[tmp]=false;
            }
            if(opr==4){
                if(bookind[tmp]>0&&!islocked[bookind[tmp]]){
                    cout<<bookind[tmp]<<endl;
                    bookind[tmp]=-1;
                }else cout<<-1<<endl;
            }
            if(opr==5){
                if(bookind[tmp]==-1)
                    bookind[tmp]=0;
            }
        }
    }
    return 0;
}

发表于 2022-03-04 21:53:30 回复(0)
补一个Java 版本
import java.io.*;
import java.util.HashMap;

public class Main{
public static void main(String[] args) throws IOException {
        //经典输入数字
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        String[]lineargs = br.readLine().trim().split(" ");
        int Q = Integer.parseInt(lineargs[2]);
        //statemapp 1代表在书架 2代表被小团借 0或者为空都代表在小美手里
        HashMap<Integer,Integer>stateMap = new HashMap<>();
        //书id->书架id
        HashMap<Integer,Integer>shelfMap = new HashMap<>();
        //shelfLock
        HashMap<Integer,Boolean>shelfLock = new HashMap<>();
        for(int i=0;i<Q;i++){
            lineargs = br.readLine().trim().split(" ");
            if(lineargs[0].compareTo("1") == 0){
                //add book
                int bookId = Integer.parseInt(lineargs[1]);
                int shelfId = Integer.parseInt(lineargs[2]);
                if(stateMap.containsKey(bookId)){
                    int state = stateMap.get(bookId);
                    if(state == 2)
                        continue;
                    if(state == 1){
                        int oldShelfId = shelfMap.get(bookId);
                        if(shelfLock.containsKey(oldShelfId)&&shelfLock.get(oldShelfId)){
                            //lock
                            continue;
                        }
                    }
                }
                if(shelfLock.containsKey(shelfId)&&shelfLock.get(shelfId)){
                    //new lock
                    continue;
                }
                stateMap.put(bookId, 1);
                shelfMap.put(bookId, shelfId);
            } else if(lineargs[0].compareTo("2") == 0){
                int shelfId = Integer.parseInt(lineargs[1]);
                shelfLock.put(shelfId, true);
            } else if(lineargs[0].compareTo("3") == 0){
                int shelfId = Integer.parseInt(lineargs[1]);
                shelfLock.put(shelfId, false);
            } else if(lineargs[0].compareTo("4") == 0){
                int bookId = Integer.parseInt(lineargs[1]);
                if(stateMap.containsKey(bookId)&&stateMap.get(bookId) == 1){
                    int shelfId = shelfMap.get(bookId);
                    if(!shelfLock.containsKey(shelfId) || shelfLock.get(shelfId) == false){
                        stateMap.put(bookId, 2);
                        shelfMap.remove(bookId);
                        writer.write(Integer.toString(shelfId));
                        writer.write("\n");
                        continue;
                    }
                }
                writer.write("-1\n");
            } else if(lineargs[0].compareTo("5") == 0){
                int bookId = Integer.parseInt(lineargs[1]);
                if(stateMap.containsKey(bookId)&&stateMap.get(bookId) == 2){
                    stateMap.put(bookId, 0); //归还
                }
            }
        }
        writer.flush();
    }
}


发表于 2021-09-04 13:09:50 回复(0)
n,m,q=map(int, input().split())
lib = [0 for _ in range(n)] #每本书的对应货架号或者小美闲置0或者小团手上-1
loc = [0 for _ in range(m)] #对应编号货架是否上锁
for _ in range(q):
    a = list(map(int, input().split()))
    if a[0]==1:
        if lib[a[1]-1] == -1&nbs***bsp;(lib[a[1]-1]>0 and loc[lib[a[1]-1]-1]==1)&nbs***bsp;loc[a[2]-1]==1:continue
        else:lib[a[1]-1]=a[2]
    elif a[0]==2: loc[a[1]-1] = 1
    elif a[0]==3: loc[a[1]-1] = 0
    elif a[0]==4:
        if lib[a[1]-1]>0 and loc[lib[a[1]-1]-1]==0:
            print(lib[a[1]-1])
            lib[a[1]-1] = -1
        else:print(-1)
    else:
        if lib[a[1]-1] == -1: lib[a[1]-1] = 0

发表于 2021-09-01 09:54:51 回复(0)
N和M确实输入设置和题目定义弄反了
发表于 2021-08-07 23:37:20 回复(0)