紫书上 说这道题是对初学者的基础练习(没错 看来是为我量身打造的
实训了五六天没做过题 所以抱着恢复点状态的心态选了这道题
谁曾想 不但没恢复 还着实给我打击了一顿
刚开始看不太懂题 后来靠着输入输出的样例 读懂了题
因为很久没做题 还是蛮期待的 于是就没有思考清晰 就直接动手做了
结果扑街了 我花了一整天到晚上十点钟 终于把题目做出来了 结果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();
}
}
}
总结心得:
最近学习了软件工程:前期的准备工作越充分,后期为补救错误付出的代价就越小。
感觉这个理论放到我做题上面 也是很有用,真的切勿心急,认真审题,捋清思路再去做,不然到时候改的时候难受死你!
还有一定就是 合适的数据结构真的很重要,很多时候我就懂的皮毛 就在那里瞎用,做到一半发现这个不能用,那个效率也不高,这就真的痛苦了。
所以还是的好好学习,认真的学,切勿半桶水。