map状态判重

本文解析CodeForces上的一道游戏策略题,通过使用队列和map数据结构,模拟了两人之间的牌类游戏过程,详细介绍了如何判断游戏是否会出现无限循环,以及如何确定胜者和游戏轮数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/problemset/problem/546/C
题意大意: 给一个n(<=10)表示两人手中共有n张牌,接下来一行表示第1个人有k1张牌,k1 v1[1] v1[2]…v1[k1], v1[i]表示第i 张牌的大小,第三行表示第2个人 有k2张牌,k2 v2[1] v2[2]…v2[k2], v2[i]表示第i 张牌的大小。每一轮,两人从牌顶部各出一张,谁出的牌大则两张牌归谁,把对方和自己的牌放入到自己牌的底部,直到其中一个人 手中没有牌出,则那个人输了。问需要多少轮,哪个人赢了。如果没有解则输出-1(k1 + k2 = n)

//用两个队列模拟就可以了。当游戏次数太多时可以输出-1

//如果严格的来判断游戏会不会结束。
//可以用map保存两个人手中的状态
map<queue<int>, map<queue<int>,int> >m;

while(!q1.empty()&&!q2.empty())
    {
        ans++;
        /**************/
        m[q1][q2]++;  //每轮游戏开始时,记录当前状态存在
		/*************/
        
        int a=q1.front(), b=q2.front();
        q1.pop(), q2.pop();

        if(a>b)
        {
            q1.push(b), q1.push(a);
        }
        else
        {
            q2.push(a), q2.push(b);
        }
		
		/**************/
        if(m[q1][q2]==1)//每轮游戏结束时,判断新状态是否已经存在
        {
            printf("-1\n");

            return 0;
        }
        /*************/
    }

思考:map对状态判重有奇效。

全部代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//#define p1 first
//#define p2 second
//memset(a, 0, sizeof(a));
//stack堆栈 queue队列 priority_queue优先队列
//vector向量 multiset平衡二叉树 deque双端队列
//pair{T1 first;T2 second;} greater<T>
//unordered_map 哈希map

queue<int> q1, q2;
map<queue<int>, map<queue<int>,int> >m;
int main()
{
    int n, a, cut=0, ans=0;
    scanf("%d",&n);
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a);
        q1.push(a);
    }

    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a);
        q2.push(a);
    }

    while(!q1.empty()&&!q2.empty())
    {
        ans++;
        m[q1][q2]++;
        int a=q1.front(), b=q2.front();
        q1.pop(), q2.pop();

        if(a>b)
        {
            q1.push(b), q1.push(a);
        }
        else
        {
            q2.push(a), q2.push(b);
        }

        if(m[q1][q2]==1)
        {
            printf("-1\n");

            return 0;
        }
    }
    if(!q1.empty())
    {
        printf("%d 1\n",ans);
    }
    else
    {
        printf("%d 2\n",ans);
    }

    return 0;
}
### Java 中的空操作 在 Java 编程中,空是一种常见的需求,尤其是在处理对象引用时。以下是几种常见的方式来进行空操作: #### 1. **基本类型的空** 基本数据类型(如 `int`, `float` 等)本身无法为 `null`,因为它们不是引用类型。然而,当使用其包装类(如 `Integer`, `Float`)时,这些包装类可以为 `null`。 ```java Integer num = null; if (num == null) { System.out.println("num is null"); } ``` 上述代码展示了如何通过简单的比较来检测一个包装类是否为 `null`[^1]。 --- #### 2. **对象的空** 对于对象引用变量,可以直接使用 `==` 运算符来断它是否为 `null`。 ```java String str = null; if (str == null) { System.out.println("str is null"); } else { System.out.println(str.length()); } ``` 需要注意的是,在调用对象的方法之前,应先对其进行空,以避免抛出 `NullPointerException`。 --- #### 3. **字符串的特殊空方式** 除了普通的 `== null` 断外,还可以结合 `isEmpty()` 方法来进一步验证字符串的内容是否为空白字符。 ```java String text = ""; if (text == null || text.isEmpty()) { System.out.println("The string is either null or empty."); } ``` 此外,也可以使用正则表达式或其他工具库函数来增强空逻辑,例如 Apache Commons Lang 库中的 `StringUtils.isBlank(String)` 方法。 --- #### 4. **集合类的空** 针对集合类(如 `List`, `Set`, `Map`),不仅需要检查其是否为 `null`,还需要确认其中是否有实际元素存在。 ```java import java.util.List; List<String> list = List.of(); if (list != null && !list.isEmpty()) { System.out.println("List contains elements."); } else { System.out.println("List is null or empty."); } ``` 此代码片段说明了如何安全地访问集合并执行后续操作。 --- #### 5. **数组的空** 与集合不同,数组不会自动提供内置方法来帮助我们完成这一任务;因此我们需要手动编写相应的条件语句。 ```java String[] array = {}; if (array == null || array.length == 0) { System.out.println("Array is null or has no elements."); } ``` 这里强调了即使数组非空也有可能长度为零的情况。 --- #### 6. **复杂结构下的深拷贝前后的空** 如果涉及到复杂的嵌套对象或者列表等场景下做深拷贝前后都需要仔细考虑可能出现的各种边界情况包括但不限于原对象及其内部子属性都可能存在的状态即全量均为NULL或者是部分字段缺失等问题所以建议采用稳妥的做法就是逐层递归遍历每一个节点直至最底层为止然后再逐一定每个环节是否存在有效值最后再决定整体返回结果的状态码从而达到精准控制流程走向的目的具体可参见下面给出的例子: ```java public class DeepCopyExample { public static void main(String[] args) throws Exception { MyClass original = new MyClass(1, "test", new MyObject("nested")); // Perform deep copy. MyClass copied = original.deepCopy(); // Check both objects are not the same instance but have equal content. if(copied != null){ System.out.println("Copied object exists and can be used safely."); } } } class MyObject implements Cloneable{ private String value; public MyObject(String value){this.value=value;} @Override protected Object clone()throws CloneNotSupportedException{return super.clone();} } ``` 以上示例演示了一个完整的深拷贝过程以及随后必要的安全性核查措施确保新创建出来的副本能够独立运作而不受原始版本的影响同时也不会因意外引入未初始化指针而导致崩溃风险提升系统稳定性表现更佳[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值