贪心算法练习day1

练习1--翻硬币

1)题目及要求

2)解题思路

输入的是字符串,要想将两组字符串进行一一对比,需要将字符串转换成字符数组,再使用for循环依次遍历字符数组,进行比对。

输入两行字符串,转换成两个字符数组;将初始数组和目标数组进行逐个对比,运用三目运算符进行判断

3)详细代码

java 复制代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        String origin=scan.next();
        String target=scan.next();
        char[] originLine=origin.toCharArray();
        char[] targetLine=target.toCharArray();
        int result=0;
        for(int i=0;i<originLine.length-1;i++){
          if(originLine[i]!=targetLine[i]){
            originLine[i]=originLine[i]== '*'?'o':'*';
            originLine[i+1]=originLine[i+1]== '*'?'o':'*';
            result++;
          }
        }
        scan.close();
        System.out.println(result);
    }
}

4)本题核心

java 复制代码
 if(originLine[i]!=targetLine[i]){
            originLine[i]=originLine[i]== '*'?'o':'*';
            originLine[i+1]=originLine[i+1]== '*'?'o':'*';
            result++;
          }

练习2--付账

1)题目及要求

2)解题思路

让每个人尽可能付接近平均金额的钱数

根据金额和人数计算平均金额;对每个人的钱数进行从小到大排序;遍历排序后,将钱数少于平均金额的人 全部支付,再从总金额里减去该人所支付的金额;重新计算平均金额,剩余金额/剩余人数,同样钱数少于新平均金额的人也全部支付;最后钱最多的人支付剩余的。以此类推

3)详细代码

java 复制代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;

/**
 * 贪心:为了使得标准差最小,每一个出的钱bi必须接近平均值s/n
 * [1]第i个人带的钱不够平均数avg,那么他只能出自己全部的钱ai
 * [2]第i个人带的钱比平均数avg多,那么他可以多付一些。
 *
 * 基本步骤如下:
 * 1、对ai从小到大排序
 * 2、排序后前一部分人的钱不够,那么就出他们所有的钱
 * 3、从总付钱数中扣除前一部分人出的钱,得剩余需要出得钱数为S',
 * 以及剩余得后一部分人的出钱平均数avg'
 * 4、后一部分人的钱多,他们多出一些:
 * (1)比较有钱的,但是他的钱也不够avg',那么他的钱也是全部出
 * (2)非常有钱的,不管怎么付他都有富余
 */
public class Main {
    public static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    public static void main(String[] args) throws IOException {
        int n = nextInt();
        long s = nextLong();
        long[] a = new long[n];

        //每个人带的钱数
        for (int i = 0; i <n ; i++) {
            a[i]=nextLong();
        }
        //开始贪心选择
        Arrays.sort(a);//排序,从小到大
        double avg=1.0*s/n;
        double sum=0;
        for (int i = 0; i <n; i++) {
            if(a[i]*(n-i)<s){   //把钱全部拿出的人
                sum+=(a[i]-avg)*(a[i]-avg);
                s-=a[i];    //更新还差多少钱
            }else{  //不需要把钱全部拿出的人。剩下的人中,钱最少的人都可以达到cur_avg
                double cur_avg=1.0*s/(n-i);//注意这里的s是还差多少钱
                //如果这个人有钱付,那么后面的人一定也能付,所以直接乘后面的人数(n - i)即可
                sum+=(cur_avg-avg)*(cur_avg-avg)*(n-i);
                break;
            }
        }
        System.out.printf("%.4f",Math.sqrt(sum/n));
    }
    public static int nextInt() throws IOException{
        st.nextToken();
        return (int)st.nval;
    }
    public static long nextLong() throws IOException{
        st.nextToken();
        return (long)st.nval;
    }
}

4)本题核心

java 复制代码
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.util.Scanner;  
  
public class Main {  
    public static void main(String[] args) throws IOException {  
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
        Scanner scanner = new Scanner(br);  
  
        int n = scanner.nextInt();  
        long s = scanner.nextLong();  
        long[] a = new long[n];  
  
        for (int i = 0; i < n; i++) {  
            a[i] = scanner.nextLong();  
        }  
  
        // ... (其余代码逻辑保持不变)  
    }  
}
  1. 输入和初始化

    • 通过StreamTokenizerBufferedReader从标准输入读取数据。
    • nextInt()nextLong()方法用于读取整数和长整数。
    • 初始化变量n(人数)、s(总金额需求)和a数组(每个人持有的钱)。
  2. 排序

    • 使用Arrays.sort(a)a数组进行排序,以确保从小到大的顺序。这是贪心策略的一部分,因为我们希望先使用钱较少的人来尽量接近平均值。
  3. 计算平均值

    • 计算总需求s的平均值avg
  4. 贪心选择

    • 遍历排序后的a数组。对于每个人,我们检查他们是否有足够的钱来支付平均值。
      • 如果某人的钱不足以支付平均值(即a[i] * (n - i) < s),那么他们会把所有的钱都拿出来。此时,我们更新总需求s,并计算这个人与平均值的差的平方,累加到sum中。
      • 如果某人的钱足够支付平均值,那么他们会支付平均值的金额,而后面的所有人也都能至少支付这个金额。因此,我们计算当前平均值与总平均值的差的平方,并乘以剩余的人数(n - i),然后累加到sum中。之后,我们跳出循环,因为没有必要再检查后面的人。
  5. 计算标准差

    • 使用公式Math.sqrt(sum / n)计算标准差,并保留四位小数后输出。这里,sum是每个人与平均值的差的平方的总和,而n是人数。标准差是衡量这组数分布离散程度的指标。
相关推荐
LAOLONG-C2 分钟前
暂存一下等会写
算法
ChoSeitaku11 分钟前
NO.94十六届蓝桥杯备战|图论基础-单源最短路|常规dijkstra|堆优化dijkstra|bellman-ford|spfa(C++)
c++·算法·图论
孤蓬&听雨38 分钟前
Axure高保真AI算法训练平台
人工智能·算法·ai·产品经理·axure·原型设计
敲上瘾1 小时前
高并发内存池(四):内存释放原理与实现
c++·算法·缓存·线程·高并发内存池·池化技术
tkevinjd2 小时前
并查集(力扣1971)
算法·leetcode·图论·并查集
Dovis(誓平步青云)2 小时前
【数据结构】励志大厂版·初阶(复习+刷题):线性表(顺序表)
c语言·数据结构·经验分享·笔记·学习·算法·学习方法
是Dream呀3 小时前
深度学习算法:从基础到实践
人工智能·深度学习·算法
Y1nhl3 小时前
搜广推校招面经七十五
人工智能·深度学习·算法·机器学习·支持向量机·推荐算法·搜索算法
Brookty3 小时前
【算法】归并排序
数据结构·算法·排序算法
星星火柴9366 小时前
数据结构:哈希表 | C++中的set与map
数据结构·c++·笔记·算法·链表·哈希算法·散列表