贪心算法练习笔记(一)

1.贪心算法

每次都选择当前最好的,当前不考虑整体,用局部最优解最后得到整体的最优解。(感觉最简单好理解的一个算法)

2.输入M,N,及N组数据,F[i],J[i];M是你有的资本,获取F[i]就要付出对应的J[i],钱不够可以按比例获取,求能获取到的最大值。

 思路:每次用最少的钱获取最大的,即F[i]/J[i]最大,所以讲F[i]/J[i]排序,每次获取最大的,可以按比例,看M能获取到多少。

public class Exercise01 {

	public static void main(String[] args) {
		
		Scanner scan=new Scanner(System.in);
		int m=scan.nextInt();
		int n=scan.nextInt();
		while(m!=-1&&n!=-1){
		List<Jf> list=new ArrayList<Jf>();
		
		double max=0;
		for(int i=0;i<n;i++){
			int j=scan.nextInt();
			int f=scan.nextInt();
			Jf jf=new Jf(j,f,(double)j/f);
			list.add(jf);
		}
		Collections.sort(list);
		for(int i=0;i<list.size();i++){
			if(m>list.get(i).f){
				max+=list.get(i).j;
				m-=list.get(i).f;
			}else{
				double t=(double)m/list.get(i).f;
				max+=t*list.get(i).j;
				break;
			}
		}
		System.out.printf("%.3f",max);
		m=scan.nextInt();
		n=scan.nextInt();
	}
	}
}

class Jf implements Comparable<Jf>{

	int j;
	int f;
	double avg;
	public  Jf(int j,int f,double avg){
		this.j=j;
		this.f=f;
		this.avg=avg;
	}
	public String toString() {
		return "Jf [j=" + j + ", f=" + f + ", avg=" + avg + "]";
	}

	public int compareTo(Jf o) {
		
	     if(this.avg-o.avg > 0.001)  
	            return -1;  
	        else  
	            return 1; 
	}
}


3.//一房间往另一房间移桌子,只有一条通道,相交的房间之间不能同时移,不相交的可以同时移,移一次10分钟,求最小时间。房间号0~400。

   思路:1.可以根据题意模拟,复杂度有点高。2.可知,每次移动的两房间之间的所有房间号都只能出现一次,出现两次就相交了,所有记录所有经过的房间次数,经过次数最大也就是移动的最小次数。

import java.util.*;
public class Exercise02 {
	//一房间往另一房间移桌子,只有一条通道,相交的房间之间不能同时移,不想交的可以同时移,移一次10分钟,求最小时间。
	public static void main(String[] args){
		Scanner scan=new Scanner(System.in);
		int t=scan.nextInt();
		while(t--!=0){
			int[] cout=new int[401];
			int n=scan.nextInt();
			while(n--!=0){
				int start=scan.nextInt();
				int end=scan.nextInt();
				int l=Math.min(start, end);
				int r=Math.max(start, end);
				for(int i=l;i<=r;i++){
					cout[i]+=10;
				}
			}
			Arrays.sort(cout);
			System.out.println(cout[400]);
		}
	}
3. //第一根木棒需要1min的准备时间;在加工了一根长为l,重为w的木棒之后,接着加工一根长为ll(l<=ll),重为ww(w<=ww)的木棒是不需要任何准备时间的。否则需要一分钟的准备时间。给定n根木棒,你要找到最少的准备时间。例如现在有长和重分别为(4,9),(5,2),(2,1),(3,5)和(1,4)的五根木棒,那么所需准备时间最少为2min,顺序为(1,4),(3,5),(4,9),(2,1),(5,2)。
思路:先给数据排序,l大的排前,l相等w大的排前。(因为要利用list遍历时有remove操作,所以要从后往前遍历,从前往后不行,所以小的再最后),利用list每次比较前一个,l和w都比当前的大更改当前l和w为它的l和w并移除它,计数器count+1,循环到list.size=0。

import java.util.*;
public class Exercise03 {

	public static void main(String[] args) {
		
		//第一根木棒需要1min的准备时间;
		//在加工了一根长为l,重为w的木棒之后,接着加工一根长为ll(l<=ll),重为ww(w<=ww)的木棒是不需要任何准备时间的。否则需要一分钟的准备时间。
		//给定n根木棒,你要找到最少的准备时间。例如现在有长和重分别为(4,9),(5,2),(2,1),(3,5)和(1,4)的五根木棒,
		//那么所需准备时间最少为2min,顺序为(1,4),(3,5),(4,9),(2,1),(5,2)。
		Scanner scan=new Scanner(System.in);
		int t=scan.nextInt();
		while(t--!=0){
			int n=scan.nextInt();
			int count=0;
			List<Stick> list=new ArrayList<Stick>();
			for(int i=0;i<n;i++){
				Stick stick=new Stick();
				stick.setL(scan.nextInt());
				stick.setW(scan.nextInt());
				list.add(stick);
			}
			Collections.sort(list);
			while(list.size()!=0){
				count+=1;
				if(list.size()==1){
					break;
				}
				int l=list.get(list.size()-1).getL();
				int w=list.get(list.size()-1).getW();
				list.remove(list.size()-1);	
				for(int i=list.size()-1;i>=0;i--){
					if(list.get(i).getL()>=l&&list.get(i).getW()>=w){
						l=list.get(i).getL();
						w=list.get(i).getW();
						list.remove(i);
					}
					
				}
			}
			System.out.println(count);
		}
	}
	
}
class Stick implements Comparable<Stick> {
	int l;
	int w;
	public String toString() {
		return "Stick [l=" + l + ", w=" + w + "]";
	}
	public int getL() {
		return l;
	}
	public void setL(int l) {
		this.l = l;
	}
	public int getW() {
		return w;
	}
	public void setW(int w) {
		this.w = w;
	}
	@Override
	public int compareTo(Stick o) {
		if(this.l!=o.l){
			return o.l-this.l;
		}else{
			return o.w-this.w;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值