第13章贪心算法

贪心算法

局部最优求得总体最优

适用于桌上有6张纸币,面额为100 100 50 50 50 10,问怎么能拿走3张纸币,总面额最大?---拿单位价值最高的

  1. 只关注局部最优----关注拿一张的最大值
  2. 拆解-----拿三次最大的纸币

不适用于桌面三件物品,每个物品都有重量和价值,

w v

6 9

5 7

3 3

承重为8,求不超过背包承重情况下最大价值

  1. 只能选一件,能不能得到最大值----选 6 9
  2. 还剩下二,能选第二件吗?不能选

所以不适用,因为不能局部最优求得总体最优

贪心算法的设计就是一次一次用偏序关系证明贪心策略

偏序关系

在数学中,偏序集合是有序理论中,指配备了部分排序关系的集合(集合没有顺序,但加了一个用于排序的关系),将排序,顺序或排列这个元素的直觉概念抽象化。

使用偏序关系的传递性:xRy,yRz-->xRz,局部最优使得全局最优

例题1-国王游戏

排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

输出一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

Ci=Aj/Bi :累乘从0到i-1

微扰:调整i和i+1位置的大臣,观察序列前后的变化:

微调的两个元素Ai和Ai+1只会改变他们两本身:所以微调后的Ci'和Ci+1'同时小于Ci+!

AixBi >= Ai+1xBi+1 :越小越往前,越大越往后

c++ 复制代码
#include <iostream>
#include <algorithm>

using namespace std;
#define MAX_N 1000
int a[MAX_N+5],b[MAX_N+5],ind[MAX_N+5]; //使用ind不对原数组排序,对下标数组排序
void acm_1_6_paixu_GuowangYouxi_test(){
//    A[i]xB[i] >= A[i+1]xB[i+1] :越小越往前,越大越往后
    int n;
    cin >> n;
    for(int i=0;i<=n;i++){
        cin >>a[i]>>b[i]; //左右手
        ind[i]=i;
    }
    sort(ind+1,ind+n+1,[&](int i,int j)->bool{
        return a[i]*b[i]<a[j]*b[j];
    });
    //统计大臣获得的最多金币数量
    int p=a[0],ans=0;
    for (int i=1;i<=n;i++){
        if(p/b[ind[i]]) //ind[i]表示排完序之后大臣的编号
            ans=p/b[ind[i]];
        p*=a[ind[i]];
    }
    cout << ans<<endl;

}
int main(){
	acm_1_6_paixu_GuowangYouxi_test();
	return  0;
}
python 复制代码
def acm_1_6_paixu_GuowangYouxi_test():
	n=int(input())
	a=list(range(n+1))
	b=list(range(n+1))
	ind=list(range(n+1))
	for i in range(n+1):
		a[i],b[i]=list(map(int,input().split()))
		ind[i]=i
	ind[1:]=sorted(ind[1:],key=lambda i:a[i]*b[i]) #按照a[i]*b[i]从小到大排序
	ans=0
	p=a[0]
	for i in range(1,n+1):
		if(p//b[ind[i]]>ans):
			ans=p//b[ind[i]]
		p*=a[ind[i]]  #左边所有大臣左手累乘
	print(int(ans))
acm_1_6_paixu_GuowangYouxi_test()

最大整数

局部最优:a+b > b+a

arr.sort(key=cmp_to_key(cmp2))

python 复制代码
from functools import cmp_to_key
def cmp2(a,b):
    if a + b > b + a: #大于
        return -1
    elif a + b < b + a: #小于
        return 1
    else:
        return 0 #相等
def test():
    n=int(input())
    arr = input().split()
    arr.sort(key=cmp_to_key(cmp2))
    print("".join(arr))
test()
c++ 复制代码
#include <string.h>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
bool cmp(const string &a,const string &b){
    return a+b > b+a;
}
int main(){
    vector<string> arr;
    string s;
    int n;
    cin >> n;
    for (int i=0;i<n;i++){
        cin >> s;
        arr.push_back(s);
    }
    sort(arr.begin(),arr.end(),cmp);
    for(int i=0;i<n;i++){
        cout <<arr[i];
    }
    cout <<endl;

}

删除

每次删除一位,保证删除一位后得到的结果位删除一位最小值

c++ 复制代码
#include <iostream>
using namespace std;
#define MAX_N 500

int main(){
    char s[MAX_N+5];
    int k;
    cin >> s >>k;
    for(int i=0;i<k;i++){ //进行k次删除,每次删除一位
        int j=0;
        //留下n-1位的最小值
        while(s[j+1] !='\0' && s[j] <= s[j+1]){
            ++j;
        }
        //12343 //得到第一个逆序位高位4
        while(s[j]) s[j]=s[j+1],j++; //后面的向前移动
        //完成一轮删除
    }
    for(int i=0,flag=1;s[i];i++){
        if(s[i]=='0' && flag){
            //首位0不输出
            //flag表示有没有输出过数字
            continue;
        }
        cout << s[i];
        flag=0;
    }
    cout <<endl;
	return  0;
}
python 复制代码
#!/usr/bin/python3
# _*_ coding: utf-8 _*_
#
# Copyright (C) 2024 - 2024 Cry, Inc. All Rights Reserved 
#
# @Time    : 2024/4/10 11:47
# @Author  : Cry
# @File    : 删数、.py
# @IDE     : PyCharm

s=input()
n=int(input())
for i in range(n):
    for j in range(len(s)+1):
        if j+1==len(s):
            s=s[:j]+s[j+1:]
            break
        if s[j]>s[j+1]:
            s=s[:j]+s[j+1:]
            break
print(int(s))

HZOJ 503独木舟

每次找最重和最轻的坐在一起

能坐在一起就一起走

不能坐在一起,就只让重的坐一条船

c++ 复制代码
//
// Created by cry on 2024/4/10.
//
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void acm_1_13_tanxin_DumuZHou_test(){
    int w,n;
    cin >>w >> n;
    vector<int> arr(n);
    for(int i=0;i<n;i++){
        cin >> arr[i];
    }
    sort(arr.begin(),arr.end());
    int i=0,j=n-1,cnt=0; // i为最轻的 j为最重的
    while(i<j){
        //最轻的和最重的能不能坐一个船
        if(arr[i]+arr[j]<=w){
            i++,j--;
        }else
            j--;
        cnt+=1;
    }
    if(i==j) cnt+=1; //还剩一个人
    cout << cnt<<endl;
}
python 复制代码
#!/usr/bin/python3
# _*_ coding: utf-8 _*_
#
# Copyright (C) 2024 - 2024 Cry, Inc. All Rights Reserved 
#
# @Time    : 2024/4/10 12:22
# @Author  : Cry
# @File    : 独木舟.py
# @IDE     : PyCharm

w=int(input())
n=int(input())
arr=list(range(n))
for i in range(n):
    arr[i]=int(input())
arr=sorted(arr)
i=0
j=n-1
cnt=0
while(i<j):
    if(arr[i]+arr[j]<=w):
        i+=1
        j-=1
    else:
        j-=1
    cnt+=1
if(i==j):
    cnt+=1
print(cnt)
相关推荐
江畔柳前堤5 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore6 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考8 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX8 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面9 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号9 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽10 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI10 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者11 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者11 小时前
【征程6】校准量化中HistogramObserver解析
算法