• Shooting Contest 射击比赛 [POJ1719] [CEOI1997] [一题多解]


    Description(下有中文题意)

    Welcome to the Annual Byteland Shooting Contest. Each competitor will shoot to a target which is a rectangular grid. The target consists of r*c squares located in r rows and c columns. The squares are coloured white or black. There are exactly two white squares and r-2 black squares in each column. Rows are consecutively labelled 1,..,r from top to bottom and columns are labelled 1,..,c from left to right. The shooter has c shots. 
    A volley of c shots is correct if exactly one white square is hit in each column and there is no row without white square being hit. Help the shooter to find a correct volley of hits if such a volley exists. 
    Example 
    Consider the following target: 

    Volley of hits at white squares in rows 2, 3, 1, 4 in consecutive columns 1, 2, 3, 4 is correct. 
    Write a program that: verifies whether any correct volley of hits exists and if so, finds one of them.

    Input

    The first line of the input contains the number of data blocks x, 1 <= x <= 5. The following lines constitute x blocks. The first block starts in the second line of the input file; each next block starts directly after the previous one. 

    The first line of each block contains two integers r and c separated by a single space, 2 <= r <= c <= 1000. These are the numbers of rows and columns, respectively. Each of the next c lines in the block contains two integers separated by a single space. The integers in the input line i + 1 in the block, 1 <= i <= c, are labels of rows with white squares in the i-th column.

    Output

    For the i-th block, 1 <= i <= x, your program should write to the i-th line of the standard output either a sequence of c row labels (separated by single spaces) forming a correct volley of hits at white squares in consecutive columns 1, 2, ..., c, or one word NO if such a volley does not exists.

    Sample Input

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

    Sample Output

     

    2 3 1 4
    NO

     

    Hint

    R,C<=1000

    给你一个r*c的矩阵,然后这个矩阵每一列有两个格子是白色的,然后你在每列上开一枪,可以打这列的任意的白色格子,问你打到的格子所在的行数是不是包括所有行了,如果包括所有行输出你在1-c列打抢的格子的行,当然这可以是不唯一的(此题为SPJ (Special Judge)),如果打不到就输出NO。

     

    Solution

    这道题的解题方法可谓是千姿百态

    一、网络流

    n我们将表示列的点编号为1到C,表示行的点编号为C+1到C+R,如果一个白色方格处在第i行第j列,那么从点j向点C+i连一条弧,弧的容量为1。再增设一个源点S,从点S往点1到C间各连一条弧,弧的容量为1,又设一个汇点T,从点C+1到点C+R向汇点T连一条弧,弧的容量为1,那么从源点S到汇点T求最大流,求出的最大流量即为最多可以射击到的行数。各条流的路线则描述了具体的射击方案。
    n显然,如果用网络流求出的最大流量比R小,则问题无解,否则我们可以根据网络流的结果求出该二分图的具体匹配方案。
    红色的连线流量为1
    蓝色的连线流量为0
    选择的射击格即为:
    (1,3), (2,1), (3,2), (4,4)
    网络流算法经过优化,时间复杂度可以达到O(C*(n+4C+4R))
     
     
    二、二分图最大匹配
    建图方法跟上面一样,换做二分图最大匹配(可以用匈牙利算法)算就行了
     

    、贪心

    1、统计所有行包含的白格数
    2、从还没有射击格的行中选出一个白格数最少的
    3、检查所选的行
     (1)若所选行的白格数为0,则输出无解;
     (2)否则从所选行的白格中任选一个作为射击格,并将与该格同列的另一个白格所处行的白格数减1
    4、返回到第2步,直到所有的行都有射击格。
    5、若还有列没有选射击格,则在该列任选一白格作为射击格即可
     
    上面的贪心方法非常高效:
    时间复杂度为O(R´C),如果在程序中使用堆优化,时间复杂度将降为O(R´log2C)。空间复杂度是线性的,而且非常容易实现。
    现在关键的问题就是——如何证明它的正确性?
     
    用h[i]表示第i行的白格数。如果最开始的时候:
    ①min{h[i]}=0:第i行已经没有办法找到可作为射击格的白格,那么问题只能无解。
    ②min{h[i]}=1:那么第i行的这一个白格必须要作为射击格,否则将因第i行没有射击格而造成问题无解。
    ③min{h[i]}≥2:那么在这一行任选一个白格,顶多只会造成剩余行中有一行h值为1,再处理那一行,最多也只会再造成剩余行中有一行h值为1,如此往复,将保持h值为1的行数不超过1行,最后最坏的情况也是造成最后一行的h值为1,继续下去所有行就都已选取了射击格了。
    因此,如果原问题有解,该贪心方法一定能找到一种正确的方案。由此可以证明,此贪心方法是正确的。确定贪心标准。
  • 相关阅读:
    深入理解vue路由的使用
    mac异常删除管理员账户恢复操作
    springMVC前后端分离开发模式下支持跨域请求
    npm 更新镜像安装Appium
    npm升级所有可更新包
    new AppiumDriver<>(new URL(url), capabilities) 报错 java.lang.NoSuchMethodError: com.google.common.base.Throwables.throwIfUnchecked(Ljava/lang/Throwable;)V
    Jmeter命令行运行实例讲解
    shodan会员命令版
    AS-REPRoasting
    Password Spraying/密码喷洒
  • 原文地址:https://www.cnblogs.com/ibilllee/p/7694265.html
Copyright © 2020-2023  润新知