贪心法练习-(Poj1328,Poj1042,最优服务次序,汽车加油问题,删数问题)

目录

  • Poj1328–Radar Installation
  • Poj1042–Gone Fishing
  • 最优服务次序
  • 汽车加油问题
  • 删数问题

Poj1328–Radar Installation

题目链接:Poj1328
题目大意:

就是给你n个岛,在x轴的上方,要你在x轴上选择最少的雷达数覆盖这n个岛,雷达的范围是d,输入n,d,并给出n个岛的(x,y)坐标,求出最少的雷达数,来覆盖这些岛屿。

解析:

利用贪心的选择,求出每个岛屿的两边所能覆盖岛的位置,然后把每个岛屿的这两个位置按照后面那个(结束的位置)排序,从第一个贪心选择就可以(和活动安排选择类似)。

import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

/**
 * 题目链接 : http://poj.org/problem?id=1328
 * @author 郑鑫
 */
public class RadarInstallation {  //提交的时候改成Main

    public static final int maxn = 1000 + 10;

    private static class Rad implements Comparable<Rad>{
        double l,r;
        public Rad() {
        }
        public Rad(double l,double r){
            this.l = l;
            this.r = r;
        }
        @Override
        public int compareTo(Rad o) {
            return r > o.r ? 1: (r == o.r ? 0: -1);
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        int kase = 0;
        while(cin.hasNext()){
            int n = cin.nextInt();
            int d = cin.nextInt();
            if(n == 0 && d == 0)break;
            System.out.print("Case " +(++kase) +": ");
            ArrayList<Rad>rad = new ArrayList<Rad>();
            boolean flag = true;
            for(int i = 0; i < n; i++){
                int x = cin.nextInt();
                int y = cin.nextInt();
                rad.add(new Rad(x - Math.sqrt(d*d*1.0 - (y*y*1.0)),x + Math.sqrt(d*d*1.0 - (y*y*1.0))));
                if(y > d)flag = false;
            }           
            if(!flag){
                System.out.println(-1);
                continue;
            }
            Collections.sort(rad);
            double End = rad.get(0).r;
            int sum = 1;
            for (int i = 1; i < n; i++) {
                if (rad.get(i).l > End) {
                    sum++;
                    End = rad.get(i).r;
                }
            }
            System.out.println(sum);
        }
    }
}

Poj1042–Gone Fishing

题目链接:Poj1042
题目大意:

John现有h个小时的空闲时间,他打算去钓鱼。钓鱼的地方共有n个湖,所有的湖沿着一条单向路顺序排列(John每在一个湖钓完鱼后,他只能走到下一个湖继续钓),John必须从1号湖开始钓起,但是他可以在任何一个湖结束他此次钓鱼的行程。题目以5分钟作为单位时间,John在每个湖中每5分钟钓的鱼数随时间的增长而线性递减。每个湖中头5分钟可以钓到的鱼数用fi表示,每个湖中相邻5分钟钓鱼数的减少量用di表示,John从任意一个湖走到它下一个湖的时间用ti表示。求一种方案,使得John在有限的h小时中可以钓到尽可能多的鱼。

解析

枚举John结束钓鱼的点,先把到这个点所需要的时间减去,然后在从0~这个点中每次贪心选取最大的,把在这里呆的时间叠加,并把相应的剩余量求出来。

import java.io.BufferedInputStream;
import java.util.Scanner;

public class GoneFishing { //提交时改成Main

    private static final int maxn = 100 + 10;
    private static final int INF = 1000000;

    public static void main(String[] args){
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        int[] f = new int[maxn],d = new int[maxn],t = new int[maxn];
        while(cin.hasNext()){
            int n = cin.nextInt();
            if( n == 0 )break;
            int h = cin.nextInt();
            for(int i = 0; i < n; i++)f[i] = cin.nextInt();
            for(int i = 0; i < n; i++)d[i] = cin.nextInt();
            for(int i = 0; i < n-1; i++)t[i] = cin.nextInt(); 
            int Time = 12 * h;
            int nowT,nowF,ans = -INF;
            int[] leftF = new int[n+1];
            int[] stayT = new int[n+1];
            int[] ansStay = new int[n+1];

            for(int i = 0; i < n; i++){
                nowT = Time; nowF = 0;
                for(int j = 0; j < n; j++)stayT[j] = 0; 
                for(int j = 0; j < i; j++){
                    nowT -= t[j];
                    leftF[j] = f[j];
                }
                leftF[i] = f[i];
                for(int j = 0; j < nowT; j++){
                    int maxx = -INF,maxk = -1;
                    for(int k = 0; k <= i; k++){
                        if(leftF[k] > maxx){
                            maxx = leftF[k];
                            maxk = k;
                        }       
                    }
                    stayT[maxk]++;
                    nowF += maxx;
                    leftF[maxk] = Math.max(0,leftF[maxk] - d[maxk]);
                }

                if(nowF > ans){
                    ans = nowF;
                    for(int j = 0; j < n; j++)ansStay[j] = stayT[j];
                }
            }

            System.out.print(ansStay[0] * 5);
            for (int i = 1; i < n; i++)System.out.print(", " + ansStay[i] * 5);
            System.out.println();
            System.out.println("Number of fish expected: " + ans + "\n");
        }
    }
}

最优服务次序

题目

这里写图片描述

解析

直接排序贪心选择小的。累加等待时间即可。

import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.Scanner;

/**
 * 题目 :  最优服务次序问题
 * @author 郑鑫
 */
public class BestSeverOrder {
    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        int n = cin.nextInt();
        int[] t = new int[n+1];
        for(int i = 1; i <= n; i++)t[i] = cin.nextInt();
        Arrays.sort(t);  //注意Arrays.sort是从1开始排序
        for(int i = 2; i <= n; i++)t[i] += t[i-1];
        double sum = 0;
        for(int i = 1; i <= n; i++)sum += t[i];
        System.out.println(sum / n);
    }
}

汽车加油问题

题目

这里写图片描述

解析

比较简答的贪心,没了就加,够就不加。

import java.io.BufferedInputStream;
import java.util.Scanner;

/***
 * 汽车加油问题
 * @author 郑鑫
 */
public class CarOils {
    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        int n = cin.nextInt();
        int k = cin.nextInt();
        int[] d = new int[k+2];
        for(int i = 0; i < k+1; i++)d[i] = cin.nextInt();
        int nowO = n,sum = 0;
        for(int i = 1; i < k+1; i++){
            if(d[i] > n ){
                System.out.println("No Solution!");
                System.exit(0);
            }
            if(nowO > d[i])nowO -= d[i];
            else{
                nowO = n - d[i];
                sum++;
            }
        }
        System.out.println(sum);
    }
}

删数问题

题目

这里写图片描述

解析

每次删除第一个当前数比后面数大的数,最后得到的就是最小的数(贪心选择)。

import java.io.BufferedInputStream;
import java.util.Scanner;
/**
 * 删数问题
 * @author 郑鑫
 */
public class DeleteNum {
    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        String s = cin.nextLine();
        int k = cin.nextInt();
        int[] a = new int[s.length() + 1];
        int len = s.length();
        for(int i = 0; i < s.length(); i++) a[i] = s.charAt(i) - '0';       
        for( ; k > 0; k--){
            int i;
            for(i = 0; i < len-1 && a[i] <= a[i+1]; i++);
            if(i != len - 1){
                for(int j = i; j < len - 1; j++)a[j] = a[j+1];
                len--;
            }
            //for(int j = 0 ;j < len; j++)System.out.print(a[j]);System.out.println();
        }
        int i;
        for(i = 0; i < len; i++)if(a[i] != 0)break;  //去除前导0
        for(; i < len; i++)System.out.print(a[i]);
        System.out.println();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值