【PAT甲级题解记录】1149 Dangerous Goods Packaging (25 分)

【PAT甲级题解记录】1149 Dangerous Goods Packaging (25 分)

前言

Problem:1149 Dangerous Goods Packaging (25 分)

Tags:map的运用 模拟

Difficulty:剧情模式 想流点汗 想流点血 死而无憾

Address:1149 Dangerous Goods Packaging (25 分)

问题描述

有一批化学货品,会发生反应的货品不能放在一个集装箱,现在两两给定会互相发生反应的化学货品,再给出每一个集装箱的货品清单,分别求这些集装箱是否可安全装箱。

解题思路

首先明确一点,若AB会反应,BC会反应,那不代表AC会反应,所以这不是一个并查集的问题,而是一个映射的问题,用map可轻松解决。

有俩个思路:

  1. 使用 map<int,map<int,int> >保存输入,输入时使两个会反应的货品之间置1,但在检查集装箱时,需要暴力检查每两个货品之间的反应关系是否为1,很可能超时。
  2. 使用 map<int,vector<int> >保存输入, 输入时保存与当前货品会发生反应的货品列表,这样在检查集装箱时,只需先初始化一个映射数组存储哪些货品出现了,然后遍历map中各个货物的反应列表,看是否有反应物出现在这个集装箱中。
  3. 或者同样使用 map<int,vector<int> >保存输入,设置一个反应货物集合,遍历集装箱货物时需检查此货物是否出现在集合中,若出现说明该货物不可放入,若没有出现则将会于该货物反应的货物入集合。

参考代码

  1. 思路2
/*
 * @Author: Retr0.Wu
 * @Date: 2022-02-22 01:06:24
 * @Last Modified by: Retr0.Wu
 * @Last Modified time: 2022-02-22 15:02:51
 */
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
unordered_map<int, vector<int> > mp; // 可用无序map提速,直接map也没问题
int main()
{
    int N, M;
    cin >> N >> M;
    for (int i = 1; i <= N; i++)
    {
        int s1, s2;
        cin >> s1 >> s2;   
        mp[s1].push_back(s2);
        mp[s2].push_back(s1);
    }
    while (M--)
    {
        int K;
        cin >> K;
        int flag = 1;
        vector<int> s(K);
        vector<int> exist(100000,0); 
        for (int i = 0; i < K; i++)
        {
            cin >> s[i];
            exist[s[i]] = 1;
        }
        for(int i=0;i<K&&flag;i++){
            for(int j = 0 ; j< mp[s[i]].size();j++){
                if(exist[mp[s[i]][j]]){  // 在这组货物中有与第i个货物反应的货物
                    flag = 0;
                    break;
                }
            }
        }
        if(flag){
            cout<<"Yes"<<endl;
        }
        else{
            cout<<"No"<<endl;
        }
    }

    return 0;
}
  1. 思路3
#include<iostream>
#include<vector>
#include<set>
#include<map>

using namespace std;
int N;  // the number of pairs of incompatible goods (1e4)
int M;  // the number of lists of goods to be shipped (1e2)
map<string,vector<string>> incompatible;
void init() {
    cin >> N >> M;
    for (int i = 0; i < N; ++i) {
        string a, b;
        cin >> a >> b;
        incompatible[a].push_back(b);
        incompatible[b].push_back(a);
    }
}

void solution_1149() {
    init();
    for (int i = 0; i < M; ++i) {
        set<string> in_pack; // 将不可兼容货物组成一个集合
        bool flag = true;
        int K;
        cin >> K;
        for (int j = 0; j < K; ++j) {
            string s;
            cin>>s;
            if(in_pack.count(s)){
                flag = false;
            }
            for(int j=0;j<int(incompatible[s].size());++j){
                in_pack.insert(incompatible[s][j]);
            };
        }
        if(flag){
            cout<<"Yes"<<endl;
        }
        else{
            cout<<"No"<<endl;
        }
    }
}
int main() {
    solution_1149();
    return 0;
}

总结

注意方法的选择,类似的方法在实际效率上可能截然不同,想清楚再开题防止误入歧途。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值