算法训练#10:思维题(2)

75 阅读3分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情

第一题

Domino on Windowsill

内容理解

以下内容是对原题的内容转化后用本人的语言总结的,原题内容是英文的,不想看英文的直接看这里就行

给出一个2×n2\times n的方格图,其中第一行的的前k1k_1个和第二行的前k2k_2个是白色的,其他都是黑色的。 然后再给出ww个规格为2×12 \times 1白色多米诺骨牌以及bb规格相同的黑色多米诺骨牌,需要把多米诺骨牌放到与其相同颜色的方格里,判定是否能够把全部骨牌放到相对应颜色的方格里(可以横着放也可以竖着放)

输入

整数tt,表示输入的案例个数,1t30001\le t \le 3000
案例的第一行输入整数nnk1k_1k2k_2,其中0k1,k2n,0n10000\le k_1,k_2\le n,0\le n \le 1000
第二行输入整数wwbb

输出

输出tt个案例的结果,每个结果输出YES表示可以,NO表示不可以

思路

若是单纯的逐个放来判定的话有点像dfs那种思想,这个思路可以实现,但对于思维题来说,还是比较复杂的,所以不到没其他方法的时候就不用这个。那我们开始从另一个角度想,既然要摆在对应颜色的方格上,而且是2×n2\times n这样的方格图,那么基本上前面的骨牌都可以竖着摆(k1k_1k2k_2都有的那部分),剩下的横着摆就行,摆放方式固定了,那么剩下的就只是数量判断问题。我们可以直接判断黑白骨牌所需的方格数和方格图上对应颜色的方格数是否相等,只有两个颜色都满足骨牌的摆放需要才输出YES,反之则输出NO

代码

import java.util.Scanner;

public class Domino {
    public static void main(String args[])
    {
        Scanner sc=new Scanner(System.in);
        int t = sc.nextInt();
        for(int i=0;i<t;i++)
        {
            int n=0;
            int k1=0;
            int k2=0;
            n=sc.nextInt();
            k1=sc.nextInt();
            k2=sc.nextInt();
            int w=0;
            int b=0;
            w=sc.nextInt();
            b=sc.nextInt();
            if(k1+k2<2*(w)||(2*n-k1-k2)<2*b)//格子的数量判断
            {
                System.out.println("no");
            }
            else
                System.out.println("yes");
        }
    }
}

第二题

Prison Break

内容理解

以下内容是对原题的内容转化后用本人的语言总结的,原题内容是英文的,不想看英文的直接看这里就行

在一个被分割成a×ba\times b间相邻房间(也就是类似上一题的方格图那样的监狱布局)的的监狱里,有个人可以在被关进去之前托关系把监狱的墙凿出洞来(别人不知道的前提下),但是他不知道他会被关进哪间牢房,所以他想让牢头在打破尽量少的墙壁的情况下无论把他关进哪个牢房他都可以越狱(越狱的前提是把在边界的墙打破,而不是只打破牢房与牢房之间的墙) image.png

这个图是一种在2×22\times 2个房间的情况下可以越狱的打破墙壁的规划(不意味着最少),黑色的是被打破的,灰色的是没被打破的

输入

整数tt,表示输入的案例个数,1t30001\le t \le 3000
每个案例输入整数aabb,其中0a,b1000\le a,b\le 100\

输出

输出tt个案例的结果,每个结果输出一个整数表示需要打破的最少的墙壁数量

思路

怎么才能做到最少呢?把外面的墙全打了再把中间的打上是肯定不行的,那肯定就是要把其中一间在边上的牢房的墙打破,然后让其他牢房都有一个到这间牢房的“通道”就可以了,这里要打出“通道”所需要打破的墙壁数量要尽量少的话,那应该就是每个相邻的房间打通一面墙就可以了,算起来,最少的墙壁数量刚好等于房间数量,这样一想,直接输出ab相乘的结果就可以了

代码

import java.util.Scanner;

public class Prison_Break{
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int a=sc.nextInt();
            int b=sc.nextInt();
            System.out.println(a*b);
        }
    }
}