Uva814 The Letter Carrier's Rounds JAVA题解

紫书上 说这道题是对初学者的基础练习(没错 看来是为我量身打造的
实训了五六天没做过题 所以抱着恢复点状态的心态选了这道题
谁曾想 不但没恢复 还着实给我打击了一顿
刚开始看不太懂题 后来靠着输入输出的样例 读懂了题
因为很久没做题 还是蛮期待的 于是就没有思考清晰 就直接动手做了
结果扑街了 我花了一整天到晚上十点钟 终于把题目做出来了 结果RE了(抱住胖胖的自己
以下是RE的代码
思路:
用 Map<String, ArrayList> 存放后期便于查询的有效地名和收件人信息
用 ArrayList[] com = new ArrayList [dis.length]; //收信人们的信息 以地名为单位存放
从而去判断
出错点 审题不仔细,思路混乱 对于何时处理数据 何时读取数据 以及跳出的循环的条件
导致后期一直修修改改 虽然答案勉强正确 但是修改花了很多时间 而且还导致代码不美观简洁 以及后期思路转换 重新修改代码的时候可直接利用的代码过少

public class UUva184{
	public static void main(String[] args) {
     Scanner in = new Scanner(System.in);
      String after = in.next();
      String next  = after;
      Map<String, ArrayList<String>> maptolocal = new HashMap<>();
    	  while(after.equals("MTA"))
    	  {     next  = after; //保存本次的 用以和上次作比较 从而判断是否该退出了
    		  /*输入地名部分*/
    	   String local = in.next();
    	   ArrayList<String> names = new ArrayList<>();
    	   int num = in.nextInt();
    	    for(;num>0;num--)
    	    {
    	    	names.add(in.next());
    	    }
           maptolocal.put(local, names);
    	  /*处理完之后 继续读另一个地名 或者 是开始输入信件*/
           		after = in.next();
    	  
    	  }
    	 /* 结束后 并进行信件的读取*/
    	  
   	  while(!(after.equals("*")&&next.equals("*")))
    	 /*  while(in.hasNext())*/
    	  {    /*after = in.next();*///保存本次的 用以和上次作比较 从而判断是否该退出了
    	        /*第一个是寄信人与收信人信息  存储并处理*/      
	    		String line = "";
		        String t = "";	
		       if(next.equals("MTA")||next.equals("*"))
		    	   t = in.nextLine(); 	
		        else
		        {
		        	next += in.nextLine();
		        	t = next;
		        }
    	  		if(t.equals(""))
    	  		{
    	  		 line = in.nextLine();
    	  		}
    	  		else {
					line = t;
				}
    	  		/*进行处理 全部都分开*/
    	        String[]  dis = line.split(" ");
    	        String  sendname = "";	//寄信人姓名
    	        String  sendlocal = ""; //寄信人地址
    	        String  takename = "";	//收信人姓名
    	        String  takelocal = ""; //收信人地址
    	        ArrayList[]  com = new ArrayList [dis.length];	//收信人们的信息 以地名为单位存放 
    	       
    	        for(int i =0;i<dis.length;i++)
    	   		{ 
    	        	int j = dis[i].indexOf('@');
    	   			com[i] = new ArrayList<>();
    	   			
    	   			if(i!=0)
    	   			{	
    	   				takename = dis[i].substring(0,j);
    	   				takelocal = dis[i].substring(j+1);
    	   				/*if(sendlocal)*/
    	   				
    	   				
    	   				
    	   				boolean f = false;
    	   					for( int c = 0;c<=i;c++)
    	   					{
    	   					if(com[c].contains(takelocal))
    	   					{   /*说明有了重复的了 所以这个也不用保存了*/
    	   						f = true;
    	   						if(!com[c].contains(takename))
    	   					   {
    	   						com[c].add(takename);    /*表示有同一个地方的收件人*/
    	   				        
    	   				        break;
    	   					   }
    	   					/*去掉重复的收件人*/
    	   					}
    	   					}
    	   				if(!f)
    	   				{   
    	   					
    	   					com[i-1].add(takelocal);
    	   					com[i-1].add(takename);
    	   					    /*否则把这个地方单独列出来 */   	   					
    	   				}
    	   			}
    	   			else	//表明是第一个 是寄件人的信息
    	   			{		
    	   				sendname = dis[i].substring(0,j);
    	   				sendlocal = dis[i].substring(j+1);
    	   			}
    	   		}
    	        
    	        /*对信件开始处理*/
    	       //读信
    	        String datum[] = new String[8];
    	        after = in.next();
    	        String da = in.nextLine();
    	        String data = "";
    	        if(da.equals(""))
    	        data = in.nextLine();//信件的具体内容
    	        else
    	        	data = da;
    	        datum[0] = in.nextLine();
    	        int a = 0;
    	       if(!datum[a].equals("*"))
    	       {
    	    	  
    	    	   while(!datum[a].equals("*"))
    	    	   {    a++;
    	    		   datum[a] = in.nextLine();

    	    	   }
    	    	   datum[a] = null;
    	       }
    	    
    	        /*输出*/
    	        
    	        
                for(int i=0;i<com.length;i++)
                {
                	if(com[i].isEmpty())
                		continue;
                	System.out.println("Connection between "+sendlocal+" and "+com[i].get(0));
                    System.out.println("     HELO "+sendlocal);
                    System.out.println("     "+250);
                    System.out.println("     MAIL FROM:<"+sendname+"@"+sendlocal+">");
                    System.out.println("     "+250);
        	        
               /* for(int k =0;k<com.length;k++)*/
                    boolean flag  = false;
                    for(int n =0;n<com[i].size()-1;n++)
    	        {
    	        	if(maptolocal.containsKey(com[i].get(0))&&maptolocal.get(com[i].get(0)).contains(com[i].get(n+1)))
    	        	{   	        		
    	        	
    	        		System.out.println("     RCPT TO:<"+com[i].get(n+1)+"@"+com[i].get(0)+">");
    	                System.out.println("     "+250);
    	                flag = true; 	        	
    	        	}
    	        	else
    	        	{
    	        	 System.out.println("     RCPT TO:<"+com[i].get(n+1)+"@"+com[i].get(0)+">");
       	             System.out.println("     "+550);
    	        	}
    	        }
    	        /*正式开始传输数据*/
    	        if(flag) {
                System.out.println("     DATA");
    	        System.out.println("     "+354);
    	        System.out.println("     "+data);
    	        if(!datum.equals("")) 
    	        {
    	        	for(int c =0;c<a;c++)
    	        System.out.println("     "+datum[c]);
    	        }
    	        System.out.println("     .");
    	        System.out.println("     "+250);
    	        }
    	        System.out.println("     QUIT");
    	        System.out.println("     "+221);
    	        }
                
               if(!after.equals("*"))/*表示存放的是信件内容 于是就赋值为* 因为信件内容读完了*/
                after = "*";
                next = in.next();
    	  }
      
		
		
	}
}

AC代码:
1 利用HashSet 来以地名和姓名的组合进行存储
后期判别收信人信息的时候 直接用存储的组合进行判别
2 LinkedHashMap<String,Integer> Local 以地址名为KEY 队形
ArrayList[] names 存放对应地址的 多个收信人姓名
names**[MAP中地址元素为KEY 对应的VALUE的值 ]** 中存储的就是对应的
人名
3 Set 判断当前收信人信息是否重复 添加

public class Uva184{
	private static final boolean String = false;

	public static void main(String[] args) {
		
     Scanner in = new Scanner(System.in);
     String info = in.next();	//标志数据存储的开始
     HashSet<String> addr = new HashSet<>();	//以地名和姓名的组合 存储
     int localsum = 0;
     
     while(!info.equals("*"))
     {
    	 String temp = in.next();	
    	 localsum++;
    	 int count = in.nextInt();
    	 while(count>0)
    	 {
    		 addr.add(in.next()+"@"+temp);	//以组合的形式传上去
    		 count--;
    	 }
    	 info = in.next();
     }
     
     /*开始读取信件的收发人*/
     String sendname ="";
     String sendlocal ="";
     String takename ="";
     String takelocal ="";
     LinkedHashMap<String,Integer> Local = new LinkedHashMap();
     ArrayList[] names = new ArrayList[localsum+1] ; //根绝地址元素的顺序 找对应的A数组
     Set<String> repeat = new LinkedHashSet<>();	//判断是否重复了
     
     
     
     info = in.next();	//存放的是第一个寄信人的Info
     while(!info.equals("*"))
     {
    	/*从@分割开来 不用函数了*/
    	 
    	 Local.clear(); //数据清理  不然会受以前数据影响
    	 repeat.clear();
    	 
    	 
    	 sendname = info.substring(0,info.indexOf("@"));
    	 sendlocal= info.substring(info.indexOf("@")+1);	//取出的字符串 不包括@
         int count  = 0;
    	 
    	 /*开始读取收信人的信息  内嵌一个while*/
    	  
    	  /**表明 收信人信息读完 故而读取内容信息*/
    	 while(!info.equals("*"))
    	     {
    		 info = in.next();
    		 if(info.equals("*"))
    			 break;
    		 takename = info.substring(0,info.indexOf("@"));
        	 takelocal = info.substring(info.indexOf("@")+1);	//取出的字符串 不包括@
    	     
        	 if(repeat.contains(info)) 
        		 continue;								//有了 说明重复了 则地名和姓名都不用存了       	 
        	 	repeat.add(info);
 
    	     if(!Local.containsKey(takelocal))
    	    	{
    	    	 Local.put(takelocal,count);
    	    	 names[count] = new ArrayList<>();
    	    	 names[count].clear();
    	    	 names[count].add(takename);
    	    	 count++;
    	    	}
    	     else
    	     {
    	    	 /*重复的已经在前面排除 说明这个一定是存在的*/
    	    	names[Local.get(takelocal)].add(takename);    	    
    	    }
    	     }
    	     
    	 /*现在开始读取信件内容*/
    	 info = in.nextLine();
    	 String[] data = new String[1000] ;
    	 int count2 = 0;
    	 if(info.equals(""))
    		 info = in.nextLine();
    	 while(!info.equals("*"))
    	 {
    		 data[count2] = info;
    		 count2++;
    		 info = in.nextLine();
    	 }     
    	 
    	 /*读完之后进行处理*/
    	 /*输出*/
	    
    	Set a =  Local.entrySet();
    	for(Map.Entry<String,Integer> entry: Local.entrySet())
        {
    		Integer takeindex = entry.getValue();
            String takesite = entry.getKey();
    		/*System.out.println("Key: "+ entry.getKey()+ " Value: "+entry.getValue());*/
     
         	 System.out.println("Connection between "+sendlocal+" and "+takesite);
             System.out.println("     HELO "+sendlocal);
             System.out.println("     "+250);
             System.out.println("     MAIL FROM:<"+sendname+"@"+sendlocal+">");
             System.out.println("     "+250);
 	          boolean flag = false;
              for(int i =0;i<names[takeindex].size();i++) {
            	  String com = names[takeindex].get(i)+"@"+takesite;
            	  System.out.println("     RCPT TO:<"+names[takeindex].get(i)+"@"+takesite+">");
              if(addr.contains(com)) {
	                System.out.println("     "+250);
	                flag = true; 	        	
	        	}
	        	else
	        	{
	             System.out.println("     "+550);
	        	}
	        }
	      //  正式开始传输数据
	        if(flag) {
            System.out.println("     DATA");
	        System.out.println("     "+354);
	        if(!data.equals("")) 
	        {
	        	for(int c =0;c<count2;c++)
	        System.out.println("     "+data[c]);
	        }
	        System.out.println("     .");
	        System.out.println("     "+250);
	        }
	        System.out.println("     QUIT");
	        System.out.println("     "+221);
	        }
         
    	info = in.next();
	     }
	        
     
	}
}

总结心得:
最近学习了软件工程:前期的准备工作越充分,后期为补救错误付出的代价就越小。
感觉这个理论放到我做题上面 也是很有用,真的切勿心急,认真审题,捋清思路再去做,不然到时候改的时候难受死你!
还有一定就是 合适的数据结构真的很重要,很多时候我就懂的皮毛 就在那里瞎用,做到一半发现这个不能用,那个效率也不高,这就真的痛苦了。
所以还是的好好学习,认真的学,切勿半桶水。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值