[编程题] 卡中心美食家
时间限制:1秒
空间限制:32768K
在卡中心隐藏了很多美食,作为一名资深吃货,楼主告诉你需要去品尝n道美味才能达成“卡中心小小美食家”的成就。这些菜品被标号为 0 到 n-1 。正所谓美食家不是一口吃成个胖子的,每道美味的品尝顺序也是有讲究的,比如西餐的上菜顺序:头盘,汤,副菜,主菜,蔬菜类菜肴,甜品,咖啡或茶。有一些美味需要“前置菜肴”,比如如果你要吃菜品0,你需要先吃菜品1,我们用一个范式来表示这些规则:[0 1]。接下来给你菜品的总数量n和m个“前置菜肴”的范式,请编程输出你为了品尝完所有美味所安排的进餐顺序。可能会有多个正确的顺序,你只要输出一种就可以了。如果不可能品尝完所有美味,返回None。
输入描述:
输入的第一行为以空格分隔的两个正整数,第一个表示原始美味总数n,第二个表示前置菜肴范式总数m。 其后m行每行均为一个以空格分隔的范式说明,第一列为待吃菜肴的标号,第二列为前置菜肴的标号。
输出描述:
对每组测试数据,单独输出一行答案,菜肴标号之间用英文逗号分隔。
输入例子1:
4 4 1 0 2 0 3 1 3 2
输出例子1:
只需输出以下任一种结果即可 0,1,2,3 或 0,2,1,3
思路梳理:1、在读入信息后,对其每个菜肴是否吃过需要建立一个标志数组,对每个菜肴为键,存储其包括的前置菜肴,由于前置菜肴数量不确定,所以需要用ArrayList来存储,用到 HashMap。
2、创建一个函数foodput,来具体实现对菜肴的放置,需要注意是否有互相制约,比如1是2的前置,2是1的前置,需要处理这种情况,调用栈来检查这种情况,当栈的长度超出了菜肴的总数,抛出异常,所以在主函数中需要处理异常;
具体代码注释:
import java.util.*;
public class Eat {
static int[] flag;//标志其每个菜肴是否已经吃过
static ArrayList<Integer> re=new ArrayList<Integer>();//存最后返回的ArrayList
static Stack<Integer> st=new Stack<Integer>();//用来判断前置菜肴和现在的是否为重叠的
static int n=0;
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
Map<Integer,ArrayList<Integer>> arr=new HashMap<Integer,ArrayList<Integer>>();
n= s.nextInt();
int len_fan=s.nextInt();
for(int i=0;i<len_fan;i++) {
int a=s.nextInt();
int v=s.nextInt();
if(arr.containsKey(a)) {
ArrayList<Integer> temp= new ArrayList<Integer>();
temp=arr.get(a);
temp.add(v);
arr.put(a,temp) ;//先得到目前的菜肴,加上后放回去
}else {
ArrayList<Integer> fan= new ArrayList<Integer>();
fan.add(v);
arr.put(a, fan);//没有的时候新建一个放入MAP
}
}
flag=new int[n];
for(int j=0;j<n;j++) {
flag[j]=0;
}
try {
for(int k=0;k<n;k++) {
foodput(arr,k);
}
//System.out.println(re);
int len_re=re.size();
for(int i=0;i<len_re-1;i++){
System.out.print(re.get(i));
System.out.print(",");
}
System.out.print(re.get(len_re-1)); //这里对输出的调整,最后一个没有,
}catch(Exception e) {
System.out.println("None");
}
}
public static void foodput(Map<Integer,ArrayList<Integer>> arr,int k) throws Exception {
if(flag[k]==0) {
st.push(k);
if(st.size()>n) {//出现互相制约的
throw new Exception();
}
if(arr.containsKey(k)) {
for(int j :arr.get(k)) {
foodput(arr,j); //这里需要递归调用其前置菜肴是否吃完
}
}
st.pop();
re.add(k);
flag[k]=1;
}
}
}