zoukankan      html  css  js  c++  java
  • SRM147 DIV1 1000

    动态规划的题,令 (dp[k][i]) 表示最后一个条纹的颜色为 (i) 且条纹数小于等于 (k) 时的旗帜个数,则有:

    (dp[k][i] = 1+sum^{颜色(j,i)可以相邻}dp[k-1][j])

    初始状态:(dp[1][i]=1)

    计算最小的 (k) 使得 (sum_i dp[k][i] geq numFlags)

    (k) 可能取得很大,时间上可能不允许做这么多次操作,注意到下面这种情况:

    存在任意一种颜色 (x) 可以与至少两种颜色 (yz) 相邻

    则可以构造出形如:(xunderline{ }xunderline{}xunderline{}xunderline{}...) 的旗帜,下换线所指任意空缺位置可以是 (y) 或 (z) 的其中一种。因此旗帜个数是关于2的指数级别,可以保证在这种情况下 (k) 足够小以致根本不用担心时间效率问题。

    另一方面,不是这种情况的颜色搭配意味着任意一种颜色只能与唯一一种颜色相邻或者不能与任何颜色相邻。

    令 (valid) 表示可以与唯一一种颜色相邻的颜色个数,(m) 表示颜色总数,(striple) 表示使得旗帜个数大于等于 (numFlags) 的最小条纹数,则:

    (striple=ceil(frac{numFlags+valid-m}{valid}))

     1 import math
     2 
     3 class Flags:
     4     def numStripes(self, numFlags, forbidden):
     5         numFlags = int(numFlags)
     6         m = len(forbidden)
     7         marks = [[True for j in range(m)] for i in range(m)]
     8         for i in range(m):
     9             s = forbidden[i].split(' ')
    10             for ch in s:
    11                 j = int(ch)
    12                 marks[i][j] = False
    13 
    14         flag = True
    15         valid = 0
    16         for i in range(m):
    17             cnt = marks[i].count(False)
    18             if cnt < m:
    19                 valid += 1
    20             if cnt < m - 1:
    21                 flag = False
    22 
    23         if flag:
    24             return math.ceil((numFlags + valid - m) / valid)
    25 
    26 
    27         dp = [1] * m
    28         k = 1
    29         while True:
    30             if sum(dp) >= numFlags:
    31                 return k
    32             dp2 = [1] * m
    33             for i in range(m):
    34                 for j in range(m):
    35                     if marks[j][i]:
    36                         dp2[i] += dp[j]
    37             k += 1
    38             dp = dp2
    39 
    40 
    41 # test
    42 o = Flags()
    43 
    44 # test else
    45 assert(o.numStripes("10", ("0 2 3", "1 2 3", "0 1 2 3", "0 1 2 3")) == 4)
    46 
    47 # test case
    48 assert(o.numStripes("10", ("0","1 2","1 2")) == 3)
    49 assert(o.numStripes("100", ("0","1","2")) == 6)
    50 assert(o.numStripes("100000000000000000", ("0","1")) == 50000000000000000)
    51 assert(o.numStripes("10000000000000000", ("0 1", "0 1", "2 3 4", "2 3 4", "2 3 4")) == 40)
    52 assert(o.numStripes("10000000000000000", ("0 1 2 3 4 5 6 7 8 9", "0 1 3 4 5 6 7 8 9", "0 2 3 4 5 6 7 8 9", "0 1 2 3 4 5 6 7 8 9", 
    53 "0 1 2 3 4 5 6 7 8 9", "0 1 2 3 4 5 6 7 8 9", "0 1 2 3 4 5 6 7 8 9", 
    54 "0 1 2 3 4 5 6 7 8 9", "0 1 2 3 4 5 6 7 8 9", "0 1 2 3 4 5 6 7 8 9")) == 4999999999999996)
    55 assert(o.numStripes("5", ("0","1","2","3","4","5")) == 1)
    View Code

    PS:当时SB的用了一个二分搜索+数列递推矩阵的算法来作,写了整整一个通宵才搞定......

  • 相关阅读:
    Centos服务器搭建(3)——安装maven
    Centos服务器搭建(2)——安装tomcat
    Centos服务器搭建(1)——安装jdk
    mysql主从复制
    Json中返回换行符处理
    github pages 绑定域名
    SharePoint学习笔记——子页面
    SharePoint学习笔记——母版页
    SSH+Oracle的整合(SSH与Oracle整合坑巨多)
    SSH整合做CRUD(大神老师整理)
  • 原文地址:https://www.cnblogs.com/valaxy/p/3444798.html
Copyright © 2011-2022 走看看