hdu2037 今年暑假不AC(贪心算法基础--会场安排类似

 

今年暑假不AC

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 22381    Accepted Submission(s): 11732

Problem Description
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%...”

确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
 
Input
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。
 
Output
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
Sample Input
  
  
12 1 3 3 4 0 7 3 8 15 19 15 20 10 15 8 18 6 12 5 10 4 14 2 9 0
 
Sample Output
  
  
5
 
Author
lcy
 
Source
 

2013-11-24 15:07:46Accepted2037171MS5088K1953 BJava1983210400

 

import java.util.Scanner;

public class hdu2037今年暑假不AC {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
          Scanner sc=new Scanner (System.in);
          while(true){
        	  int n=sc.nextInt();
        	  if(n==0)break;
        	  int[]a=new int[n];
        	  int[]b=new int[n];
        	  for(int i=0;i<n;i++){
        		  a[i]=sc.nextInt();
        		  b[i]=sc.nextInt();//结束时间
        	  } 
        	  for(int i=0;i<n-1;i++){
        		  for(int j=i+1;j<n;j++){
        			   if(b[i]>b[j]){
        			    	 int e=a[i];
        			    	 a[i]=a[j];
        			    	 a[j]=e;
        			    	 
        			    	 int t=b[i];
        			    	 b[i]=b[j];
        			    	 b[j]=t;
        			     }
        		  }
        	  }
        	  System.out.println("排序后");
        	  for(int i=0;i<n;i++)
                  System.out.println(a[i]+":"+b[i]);
                  System.out.println("=================");
        	  System.out.println("打印那些活动对应的时间安排");
        	  
        ==============第一次做时写的一个算法==============
        /*int count=1;
        	  int min=b[0];//你要考虑只有一个的时候
        	  for(int i=0;i<n-1;i++)//类似于冒泡排序的做法!!!       		
        		  for(int j=i+1;j<n;j++)//此算法不好之处在于,没有跳转,儿有很多多余的不要的操作!!!!
        			  if(min<=a[j]){//第2013年11月24日出现”黑色三分钟“,就是在此处!一道原题,一个小时半未能解决!!>_<.深深地祭奠!
        				  min=b[j];
        				  count++;
        				  // System.out.println(a[i]+" $ "+b[i]);
        				  break;
        			  }*/
        =============第二次做时写的一个算法====有所改进===========	  
        	  int count=1;
        	  System.out.println(a[0]+" $ "+b[0]);
        	  for(int i=0; i<n-1;i++)//必须i<n-1,类似于冒泡排序
        		   
        		    for(int j=i+1; j<n; j++)
        			   if(b[i]<=a[j]){
        				
       				i = j-1;//i会在改层for循环执行完毕后自身加1,所以与退回一步
        				  count++;
        				    System.out.println(a[j]+" $ "+b[j]);        				 
        				  break;
        			  }       	     		  
        	 System.out.println(count);       	  
          }
	}
}


输出结果:

12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
排序后
1:3
3:4
0:7
3:8
2:9
5:10
6:12
4:14
10:15
8:18
15:19
15:20
=================
打印那些活动对应的时间安排
1 $ 3
3 $ 4
5 $ 10
10 $ 15
15 $ 19
5


 上边的代码太挫!!(还是保留着,也是一个成长的过程)

 在有一大堆活动时,我们最先应该选择结束时间最早的那个,以利于之后能安排更多的活动,然后,再在剩下的可选的会场中选择最可能结束时间最早的那个,依次类推,直到无法安排任何活动为止。
也就是说,每次选择时,都应该贪婪的选择结束时间最短的那个活动

贪心算法是从局部的最优解去找全局的最优解,所以很有可能就像我们一样,只看眼前不看长远的话,很有可能是会走错路的。
所以,证明贪心算法的正确性就是一件极为重要的问题。

一般,贪心算法的证明多使用反证法

先假设存在一种方案B比我们刚才所说的方案A更好,也就是说,方案B能选出更多的活动。

现在假设方案B在第一次选择时没有选择结束时间最早的方案,则,方案B在选择第一个方案之后,剩余的方案中,起始时间一定要比方案A晚。所以方案B一定不可能比方案A选择出更多的活动如果方案B在第一次与方案A选择了相同的活动,而之后哪一次与方案A不同的话,则从此次之后,必然还会出现上面所说的情形。
故方案B一定不可能选出比方案一更多的活动。
所以,方案A就是最好的方案

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
          Scanner sc=new Scanner (System.in);
          while(true){
        	  int n=sc.nextInt();
        	  if(n==0)break;
        	  int[]a=new int[n];
        	  int[]b=new int[n];
        	  for(int i=0;i<n;i++){
        		  a[i]=sc.nextInt();
        		  b[i]=sc.nextInt();//结束时间
        	  } 
        	  for(int i=0;i<n-1;i++){
        		  for(int j=i+1;j<n;j++){
        			   if(b[i]>b[j]){
        			    	 int e=a[i];
        			    	 a[i]=a[j];
        			    	 a[j]=e;
        			    	 
        			    	 int t=b[i];
        			    	 b[i]=b[j];
        			    	 b[j]=t;
        			     }
        		  }
        	  }
        	  int count=1;
        	  int sta = b[0]; 
        		 for(int j=1; j<n; j++)
        			 if(sta <= a[j]){
       				     sta = b[j];
        				 count++;
        			  }       	     		  
        	 System.out.println(count);       	  
          }
	}
}

 java的类”结构体“排序:

import java.util.Arrays;
import java.util.Scanner;

public class nyoj_14_会场安排问题 {

	public static void main(String[] args) {
		 
          Scanner sc=new Scanner (System.in);
          int  C = 1;
          while(sc.hasNext()){
        	  int n=sc.nextInt();
         
        	  E [] e = new E[n];
        	  for(int i=0;i<n;i++){
        		 e[i] = new E();
        		 int x=sc.nextInt();
        		 int y=sc.nextInt();
        		 e[i].a = x>y?y:x;
        		 e[i].b= x>y?x:y;
        	  } 
        	  Arrays.sort(e);//一个类似以结构体的排序时需要用Comparator而非Comparable
        	  int count=1;
        	  int sta = e[0].b; 
        		 for(int j=1; j<n; j++)
        			 if(sta < e[j].a){
       				     sta = e[j].b;
        				 count++;
        			  }   
        		 System.out.println("Case "+(C++)+":");
        	     System.out.println(count+".");       	  
          }
	}
}
class E implements Comparable<E>{
	int a,b;
	@Override
	public int compareTo(E o) {
		 
		return this.b-o.b;
	} 
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值