首页 > 试题广场 >

重叠的装饰

[编程题]重叠的装饰
  • 热度指数:4679 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
我们部门需要装饰墙,但是墙非常非常的长,有一千万米。我们会按顺序贴很多海报在上面,这些海报相互之间会重叠,请问下,最后还能看到哪些?(只看到一部分也算)

输入描述:
N表示N张海报
接下来每一行代表海报的左右边界(上下默认全满),Li,Ri,均为整数,大于0,小于一千万。海报按输入顺序张贴。


输出描述:
有多少张海报是可见的
示例1

输入

5
1 4
2 6
8 10
3 4
7 10

输出

4
#优化过的顺序dp插入判断方法,很好理解,百分百通过
def main():
    N = int(input())
    k = [[0, i, -1] for i in range(N*2)]
    maxs = 0
    i = 0
    while i < N*2:
        a, b = map(int, input().split())
        k[i][0] = a
        k[i+1][0] = b
        i += 2
#    print(k)
    k.sort(key=lambda x:x[0])
    k[0][2] = 0
    count = 0
    for i in range(1, len(k)):
        if k[i][2] == k[i-1][2]:
            k[i][2] = count
        else:
            count += 1
            k[i][2] = count
#    print("count", count)
    dp = [-1] * (count+1)
#    print(k)
    k.sort(key=lambda x:x[1])
#    print(k)
    i = 0
#    print(dp)
    while i < len(k):
        left = k[i][2]
        right = k[i+1][2]
        for j in range(left, right+1, 1):
            dp[j] = i
        i += 2
#    print(dp)
    dic = dict()
    for i in range(len(k)):
        dic[dp[i]] = dic.get(dp[i], 0)+1
#    print(dic)
    print(len(dic))
if __name__ == "__main__":
    main()

编辑于 2020-04-11 14:35:31 回复(0)
python解 ac 80% 运行超时
给每个单位区间段一个编号,海报覆盖就相当于重叠,重新赋值一段海报长度的一样的编号
请大佬帮忙看看有无解决办法
import sys
n=int(input())
data=[]
for i in range(n):
    data.append(list(map(int,sys.stdin.readline().strip().split())))
res=[0]*10000000#给每个单位区间段一个编号,海报覆盖就相当于重叠,重新赋值一段海报长度的一样的编号
for i in range(1,n+1):
    res[data[i-1][0]:data[i-1][1]]=[i]*(data[i-1][1]-data[i-1][0])
res=set(res)
ress=len(res)-1
print(ress)


发表于 2020-03-26 15:24:36 回复(0)
"""
一个实现起来很简单的思路,通过80%用例,考试时很实用,不知道改成C或java是不是还超时
对于示例1,所有左右边界组成的集合(1, 2, 3, 4, 6, 7, 8, 10),分成七段;
借助字典从前到后为每一段赋值海报编号,
最后 每一段的值代表最上边可以看到的海报编号,
对字典的值求集合的长度,即为可见海报的张数
"""
import sys

if __name__ == "__main__":
    # sys.stdin = open("input.txt", "r")
    n = int(input().strip())
    a = []
    for _ in range(n):
        a.append(list(map(int, input().strip().split())))
    b = sorted(list(set(sum(a, []))))
    d = dict()
    for i in range(n):
        for j in range(b.index(a[i][0]), b.index(a[i][1])):
            d[str(b[j]) + '-' + str(b[j + 1])] = i
    ans = len(set(d.values()))
    print(ans)  

第二种思路
/*
对每一张海报t,
计算上一层海报未覆盖的(可见)区域(x,y),
递归调用,直到t>n,海报t仍可以被看到,返回True;
或者直到某一层将可见区域完全覆盖,返回False。
by the way: 最后一个测试用例是错的吧,通过仔细对比已通过程序,26行改为27行通过全部用例 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 10000
int n;
int a[N][2];

bool cover(int  x, int  y, int t)
{
    if (x >= y)
        return false;
    if (t >= n)
        return true;
    if (a[t][0] <= x && y <= a[t][1])
        return false;
    else if (a[t][0] >= y || a[t][1] <= x)
        return cover(x, y, t + 1);
    else if (x <= a[t][0] && a[t][1] <= y)
//        return cover(x, a[t][0], t + 1) || cover(a[t][1], y, t + 1)
        return cover(x, y, t + 1);
    else if (x < a[t][1] && a[t][1] < y)
        return cover( a[t][1], y, t + 1);
    else if (x < a[t][0] && a[t][0] < y)
        return cover( x, a[t][0], t + 1);
    return false;//所有情况都考虑到了,此句不需要;删除此句有时会编译不通过
}

int main()
{
//    freopen("input.txt", "r", stdin);
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> a[i][0] >> a[i][1];
    }
    int ans = 0;
    for(int t = 0; t < n; t++)
        if(cover(a[t][0], a[t][1], t + 1))
            ans += 1;
    cout << ans << endl;
    return 0;
}

编辑于 2019-07-11 17:45:05 回复(6)