贪心算法 openjudge 百练 python

https://www.icourse163.org/learn/PKU-1001894005?tid=1450413466#/learn/content
程序设计与算法(二)算法基础

4110:圣诞老人的礼物 未完成,可能因为浮点数

# 4110:圣诞老人的礼物
# http://bailian.openjudge.cn/practice/4110
import operator


class Box:
    def __init__(self, v, w, density):
        self.v = v  # 价值
        self.w = w  # 重量
        self.density = density  #单位重量的价值


NM = input().split()
num_boxes = int(NM[0])  # 糖果箱数正整数n(1 <= n <= 100)
MAX_weight = int(NM[1])  # 驯鹿能承受的最大重量正整数w(0 < w < 10000)
# 其余n行每行对应一箱糖果,由两部分组成,分别为一箱糖果的价值正整数v和重量正整数w,中间用空格隔开。
boxes = [0] * (num_boxes)
for i in range(0, num_boxes):
    VWDen = input().split()
    boxes[i] = Box(int(VWDen[0]), int(VWDen[1]), int(VWDen[0]) / int(VWDen[1]))
boxes.sort(key=operator.attrgetter('density'))  # 按单位重量的价值排序

totw = 0
totv = 0
for i in range(num_boxes - 1, -1, -1):  # 按单位重量的价值从大到小依次放人
    if (totw + boxes[i].w <= MAX_weight):  #未放满
        totw += boxes[i].w
        totv += boxes[i].v
    else:  #已放满
        totv += boxes[i].density * (MAX_weight - totw)
        totw = MAX_weight
        break
print(totv)

4151:电影节

# 4151:电影节
# http://bailian.openjudge.cn/practice/4151


class Movie(object):
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __lt__(self, other):  # 将所有电影按结束时间从小到大排序
        return self.end < other.end


while True:
    # 每组数据开头是n(n<=100),表示共n场电影。
    num_movies = int(input())
    # n=0则数据结束
    if not num_movies:
        break
    # 接下来n行,每行两个整数(0到1000之间),表示一场电影的放映区间
    movies = [0] * (num_movies)
    for i in range(0, num_movies):
        se = input().split()
        movies[i] = Movie(int(se[0]), int(se[1]))
    movies.sort()

    ans = 0  # 最多能看几部电影
    end = 0  # 记录已选的电影的最晚那部的结束时间
    for i in range(0, num_movies):
        if (end <= movies[i].start):  # 如果电影i开始时间比end晚
            ans += 1
            end = movies[i].end  # 更新end为电影i的结束时间
    print(ans)

4144:畜栏保留问题

# 4144:畜栏保留问题
# http://bailian.openjudge.cn/practice/4144
import operator
from queue import PriorityQueue


class Cattle:
    def __init__(self, l, r, pos):
        self.l = l  #
        self.r = r  #
        self.pos = pos  # 牛的编号

    def __lt__(self, other):  # 在优先队列中按右端点,即结束时间从小到大排序
        return self.r < other.r

    def __str__(self):
        return '(' + str(self.l) + ',' + str(self.r) + ',' + str(
            self.pos) + ',' + ')'


# 第一行包含一个整数N(1 ≤ N ≤ 50, 000),表示有N牛头
num_cattle = int(input())
# 接下来N行每行包含两个数,分别表示这头牛的挤奶时间[Ai, Bi](1 ≤ A≤ B ≤ 1, 000, 000)
cattle = [0] * (num_cattle)
for i in range(0, num_cattle):
    lr = input().split()
    cattle[i] = Cattle(int(lr[0]), int(lr[1]), i)
# 初始顺序按照左端点,即开始时间从小到大排序
cattle.sort(key=operator.attrgetter('l'))

# print('l\tr\tpos')
# for pp in cattle:
#     print(str(pp.l) + '\t' + str(pp.r) + '\t' + str(pp.pos))
# print()

q = PriorityQueue()
num_chulan = 0
use = [0] * (num_cattle + 1)  # 第i头牛所被分配的畜栏编号(从1开始)初始化为0
for i in range(0, num_cattle):
    if q.empty():  # 如果无畜栏,那么需要一个新畜栏
        num_chulan += 1
        # 第cattle[i].pos头牛的畜栏编号 = 新畜栏编号
        use[cattle[i].pos] = num_chulan
        q.put(cattle[i])
        continue

    qget = q.get()
    if (qget.r < cattle[i].l):
        # 如果有畜栏,且畜栏在cattle[i]开始的时间空闲
        # 第cattle[i].pos头牛的畜栏编号 = 该已有畜栏编号
        use[cattle[i].pos] = use[qget.pos]
    else:  # 如果有畜栏,且畜栏在cattle[i]开始的时间不空闲,那么需要一个新畜栏
        q.put(qget)
        num_chulan += 1
        # 第cattle[i].pos头牛的畜栏编号 = 新畜栏编号
        use[cattle[i].pos] = num_chulan
    q.put(cattle[i])

# 第一行包含一个整数,表示最少需要的畜栏数
print(num_chulan)
for i in range(0, num_cattle):
    print(use[i])  # 第i头牛所被分配的畜栏编号(从1开始)

1328:Radar Installation 建立雷达 运行时间错误,输入空行咋办

# 1328:Radar Installation 建立雷达
# http:#bailian.openjudge.cn/practice/1328
import operator
import math
import sys


class Seg:
    def __init__(self, x1, x2):
        self.x1 = x1  # 起点
        self.x2 = x2  # 终点


# def solve(segs, n):  # 复杂度O(n^2)
#     firstNoCovered = 0  # 目前编号最小的被覆盖的区间的编号
#     num_Radar = 1
#     for i in range(0, n):  # 第[0,n-1]段
#         for k in range(firstNoCovered, i):  # 第[firstNoCovered,i-1]段
#             if segs[k].x2 < segs[i].x1:  # 如果第k段的终点 < 第i段的起点
#                 # 那么第i段的起点无法覆盖第k段,需要新雷达
#                 num_Radar += 1
#                 firstNoCovered = i
#                 break
#     return num_Radar


def solve(segs, n):  # 复杂度O(nlogn)
    num_Radar = 1
    now = segs[0].x2  # 当前线段集合右端点的最小值
    for i in range(1, n):  # 第[1,n-1]段
        if segs[i].x1 < now:  # 如果第i段的起点 < 当前线段集合右端点的最小值
            # 那么第i段的起点可以覆盖当前线段集合
            now = min(now, segs[i].x2)
        else:  # 那么第i段的起点不能覆盖当前线段集合,需要新雷达
            num_Radar += 1
            now = segs[i].x2  # 当前线段集合右端点的最小值 = 第i段的终点
    return num_Radar


case_num = 0
# 输入包含若干组数据,每组数据的第一行是两个整数n和d,分别表示小岛的数量和雷达的半径。
while True:
    #     line = sys.stdin.readline()
    #     if not line:
    #         continue
    #     nd = line.split()

    #     try:
    #         nd = input().split()
    #     except EOFError:
    #         continue

    nd = input().split()

    n = int(nd[0])  # 小岛的数量(1≤n≤1000)
    if n == 0:
        break
    d = int(nd[1])  # 雷达的半径
    case_num += 1
    segs = [0] * n
    NoAns = False
    # 接下来有n行,每行的两个整数分别表示各个小岛的坐标。输入以0 0结束。
    for i in range(0, n):
        xy = input().split()
        x = int(xy[0])
        y = int(xy[1])
        if y > d:
            NoAns = True
            continue
        # 算出每个岛屿所需雷达的分布区间
        segs[i] = Seg(x - math.sqrt(d * d - y * y),
                      x + math.sqrt(d * d - y * y))
    if NoAns:
        print("Case " + str(case_num) + ": -1")
        continue
    # 如果可以找到一个雷达同时覆盖多个区间,那么把这多个区间按起点x坐标从小到大排序,
    # 则最后一个区间(起点最靠右的)k的起点,就能覆盖所有区间
    # 求最少的点,使得所有的线段都被覆盖到
    segs.sort(key=operator.attrgetter('x1'))  #区间按起点排序
    num_Radar = solve(segs, n)
    print("Case " + str(case_num) + ":" + " " + str(num_Radar))

1042:Gone Fishing 钓鱼

# 1042:Gone Fishing 钓鱼
# http:# bailian.openjudge.cn/practice/1042
from queue import PriorityQueue


class lake:
    def __init__(self, f, d, iden):
        # 对于每个湖i,在初始的5分钟,小明可以钓到fi条鱼,
        # 之后每过5分钟,可钓到的鱼会减少di,直到减少为0
        self.f = f
        self.d = d
        self.iden = iden

    def __gt__(self, other):  # 用优先队列维护当前所有湖能钓到的鱼,每次取出f最大的湖并更新
        if self.f == other.f:  # 如果两个类的f相等,那么类小等效于编号iden大
            return self.iden > other.iden
        else:  # 类小等效于f小
            return self.f < other.f

    def __str__(self):
        return '(' + str(self.f) + '\t' + str(self.d) + '\t' + str(
            self.iden) + ')'


# 第一行包含一个数n(2≤n≤25),表示湖的个数
n = int(input())
while n != 0:  # 输入以n=0结束。
    # 第二行包含一个数h(1≤h≤16),表示小明钓鱼的小时数
    total_time = int(input()) * 12  # 小时数换算成5分钟的倍数
    # 第三行包含n个数,给出fi(fi≥0)
    fi = input().split()
    # 第四行包含n个数,给出di(di≥0)
    di = input().split()
    lakes = [0] * n
    for ii in range(0, n):
        lakes[ii] = lake(int(fi[ii]), int(di[ii]), ii)
    # 接下来一行包含n-1个数,给出ti(0≤ti≤192)。
    inp = input().split()
    dis = [0] * n
    for ii in range(1, n):
        dis[ii] = int(inp[ii - 1])
        dis[ii] += dis[ii - 1]

    num_fish = -1
    q = PriorityQueue()
    for i in range(0, n):  # 枚举在前i个湖中钓鱼[0,n-1]
        while not q.empty():  # 清空
            q.get()
        for j in range(0, i + 1):  # [0,i]
            q.put(lakes[j])

        num_fish_tmp = 0  # 本次枚举能钓到的鱼总数
        time_fish_tmp = [0] * n  # 本次枚举在各个湖中的钓鱼时间
        fish_time = total_time - dis[i]  # 减去路程后剩余的钓鱼时间
        while fish_time > 0:  # 如果还有钓鱼时间
            fish_time -= 1
            lack_get = q.get()  # 取出当前5分钟内能钓到最多鱼的湖
            # 一定要有下面这行,因为python的 = 是引用。如果没有,那么会把lakes修改
            lack_get = lake(lack_get.f, lack_get.d, lack_get.iden)
            num_fish_tmp += lack_get.f  # 加上当前5分钟内能钓到的鱼
            time_fish_tmp[lack_get.iden] += 1  # 在lack_get湖中钓鱼的时间
            lack_get.f -= lack_get.d  # 更新该湖在下一个5分钟内能钓到的鱼数
            if lack_get.f < 0:  # 这个湖的鱼钓完了
                lack_get.f = 0
            q.put(lack_get)  # 更新了之后要放回去优先队列里面
        if num_fish_tmp > num_fish:  # 如果本次枚举能钓到的鱼总数是最多的
            num_fish = num_fish_tmp  # 更新已有的枚举中最多的 能钓到的鱼总数
            time_fish = time_fish_tmp

    # 第一行输出在每个湖中钓鱼的时间,用逗号隔开
    for i in range(0, n - 1):
        print('%d, ' % (time_fish[i] * 5), end='')
    print(time_fish[n - 1] * 5)
    # 第二行输出期望钓到的最多的鱼的数量
    print("Number of fish expected: %d" % num_fish)

    n = int(input())
    if (n > 0):
        print()

2287:Tian Ji – The Horse Racing 田忌赛马

# 2287:Tian Ji -- The Horse Racing 田忌赛马
# http://bailian.openjudge.cn/practice/2287/

n = int(input())
while True:
    # 第一行以一个正整数 n (n<=1000) 开始,即每边的马数。
    # 输入以在最后一个测试用例后有一个“0”的行结束。
    if (n == 0):
        break
    # 第二行接下来的n个整数是田的马的速度。
    tian = input().split()
    for ii in range(len(tian)):
        tian[ii] = int(tian[ii])
    # 第三行接下来的n个整数是国王的马的速度。
    king = input().split()
    for ii in range(len(king)):
        king[ii] = int(king[ii])
    tian.sort(reverse=True)
    king.sort(reverse=True)

    tianHead = 0
    kingHead = 0
    tianTail = n - 1
    kingTail = n - 1
    tian_money = 0
    while (tianHead <= tianTail):
        if (tian[tianHead] > king[kingHead]):
            # (1)田忌最快的马比齐王最快的马快,则拿这两者比赛,
            # 因为此时田忌最快的马一定能赢一场,所以选择齐王最快的马比赛是最优的。
            tianHead += 1
            kingHead += 1
            tian_money += 200
        elif (tian[tianHead] < king[kingHead]):
            # (2)田忌最快的马比齐王最快的马慢,则选择用田忌最慢的马与齐王最快的马比,
            # 因为此时齐王最快的马一定能赢一场,所以选择田忌最慢的马与之比试肯定是最优的。
            kingHead += 1
            tianTail -= 1
            tian_money -= 200
        else:  # (3)田忌最快的马与齐王最快的马速度相等,这又分为以下两种情况。
            if (tianTail == tianHead):
                break
            if (tian[tianTail] > king[kingTail]):
                # ①若田忌最慢的马比齐王最慢的马要快,则比两个最慢马,
                # 因为此时齐王最慢的马一定会输一场,
                # 所以选择田忌最慢的马与之比试肯定是最优的。
                tianTail -= 1
                kingTail -= 1
                tian_money += 200
            else:# 问题的关键是,头马一样快,且尾马也一样快,则用自己尾马对对方头马。
                # ②否则,用田忌最慢的马与齐王最快的马比,
                # 因为此时田忌最慢的马一定不能赢一场,而齐王最快的马一定不会输一场,
                # 所以选择田忌最慢的马与之比试肯定是最优的。
                if (tian[tianTail] < king[kingHead]):
                    tian_money -= 200
                tianTail -= 1
                kingHead += 1
    # 对于每个输入案例,输出一行包含单个数字,这是田忌将获得的最大金钱,以银元为单位。
    print(tian_money)
    n = int(input())
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zzz的学习笔记本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值