首页 > 试题广场 >

兵临城下

[编程题]兵临城下
  • 热度指数:1197 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
卢卡斯的驱逐者大军已经来到了赫柏的卡诺萨城,赫柏终于下定决心,集结了大军,与驱逐者全面开战。
卢卡斯的手下有6名天之驱逐者,这6名天之驱逐者各赋异能,是卢卡斯的主力。
为了击败卢卡斯,赫柏必须好好考虑如何安排自己的狂战士前去迎战。
狂战士的魔法与一些天之驱逐者的魔法属性是相克的,第i名狂战士的魔法可以克制的天之驱逐者的集合为Si(Si中的每个元素属于[0,5])。
为了公平,两名狂战士不能攻击同一个天之驱逐者。
现在赫柏需要知道共有多少种分派方案。
例:
S1={01},S2={23},代表编号为0的狂战士的魔法可以克制编号为0和编号为1的天之驱逐者,编号为1的狂战士的魔法可以克制编号为2和编号为3的天之驱逐者,共有四种方案:02,03,12,13。
02---代表第一个狂战士负责编号为0的驱逐者,第二个狂战士负责编号为2的驱逐者;
03---代表第一个狂战士负责编号为0的驱逐者,第二个狂战士负责编号为3的驱逐者;
12---代表第一个狂战士负责编号为1的驱逐者,第二个狂战士负责编号为2的驱逐者;
13---代表第一个狂战士负责编号为1的驱逐者,第二个狂战士负责编号为3的驱逐者;
S1={01},S2={01},代表编号为0的狂战士的魔法可以克制编号为0和编号为1的天之驱逐者,编号为1的狂战士的魔法可以克制编号为0和编号为1的天之驱逐者,共有两种方案:01,10。

输入描述:
多组测试数据,请处理到文件结束。
对于每组测试数据:
第一行为一个整数N,代表狂战士的数量。
第二行为N个字符串,第i个字符串表示第i个狂战士能够克制的天之驱逐者的集合。
保证:
1<=N<=6,1<=每个字符串的长度<=6,且每个字符都是0~5中的一个数字。


输出描述:
输出一个整数,代表分配方案数
示例1

输入

2
01 23
2
01 01
3
3 015 5

输出

4
2
2
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

public class Main {
	// 利用回溯+减枝
	static int answer_qty = 0;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		List<String> conquer = new ArrayList<String>();
                //用于保存当前的前k个元素的排列
		Set<Character> result = new HashSet<Character>();
                //以下为初始化过程。
		while (in.hasNext()) {
			answer_qty = 0;
			conquer.clear();
			result.clear();
			int num = in.nextInt();
			for (int i = 0; i < num; ++i) {
				conquer.add(in.next());
			}
			int index = 0;
                        //问题求解方法
			permutation(conquer, index, result);
			System.out.println(answer_qty);
		}
	}

	// 减治,将N组元素的排序问题,化简为N-1组元素的排序问题
        //利用了经典全排列问题的思想,只不过第i个位置上的元素可选的集合不再是所有元素
        //每个位置i的可选元素的集合为 conquer.get(i) //此外还有一个约束条件:选取的元素不能相同
	public static void permutation(List<String> conquer, int index, Set<Character> result) {
		if (conquer == null)
			return;
		// 排序完毕
		if (index == conquer.size()) {
			answer_qty++;
			return;
		}
		String currentRow = conquer.get(index);
		for (int i = 0; i < currentRow.length(); ++i) {
			//如果这个字符还未被使用,则可以加入到排列中
			//如果已经被使用采用,直接跳过,加快速度
			if (!result.contains(currentRow.charAt(i))) {
				result.add(currentRow.charAt(i));
				permutation(conquer, index+1, result);
				result.remove(currentRow.charAt(i));
			}
		}

	}
}

编辑于 2017-06-05 11:35:30 回复(0)
就是一棵树,求叶子节点个数
我直接遍历的
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		while (in.hasNext()) {
                        //获取输入
			int N = in.nextInt();
			String[] si = new String[N];
			for (int i = 0; i < N; i++) {
				si[i] = in.next();
			}
			int count = work(si, 0, new ArrayList<Character>(si.length));
			System.out.println(count);
		}
	}

        /**
         * 进行计算的方法
         * @param si 输入的字符串数组
         * @param i 表示进行到了树的第i层
         * @param list 保存根节点到当前节点的路径,用于判断重复
         * @return 表示当前树(子树)的可行方案数量
         */
	public static int work(String[] si, int i, List<Character> list) {
		if (i != list.size()) return 0;
		if (i >= si.length) return 0;
		int count = 0;
		String layel = si[i];
		for (int j = 0; j < layel.length(); j ++ ) {
			Character sub = layel.charAt(j);
			if (!list.contains(sub)) {
				list.add(sub);
				if (list.size() == si.length) {
					count ++;
					list.remove(si.length - 1);
					continue;
				}
				count += work(si, i + 1, list);
				list.remove(list.size() - 1);
			}
		}
		return count;
	}
} 


编辑于 2016-06-16 17:06:01 回复(2)
import java.util.*;
public class Main {
	
	public static void main(String[] args) {
		
		Scanner cin=new Scanner(System.in);
		while(cin.hasNext())
		{
			int num=cin.nextInt();
			String [] si=new String[num];
			for(int i=0;i<si.length;i++)
			{
				si[i]=cin.next();
			}
			int [] select={0,0,0,0,0,0};//初始化一个标志数组,表示每个是否被选中过,一开始都为0,表示都没被选中过
			int ans[]=new int[1];
			//Integer ans = new Integer(0);
			int n=0;
			
			dfs(n,num,ans,si,select);
			//n表示正在搜索第几个字符串,num表示字符串总数,ans表示结果,si表示字符串数组,select表示标志数组
			//for(int i=0;i<si.length;i++)
				//System.out.println(si[i]);
			System.out.println(ans[0]);
		}//while

 }//main
	private static void dfs(int n,int num,int ans[],String [] si,int [] select)
	//n表示正在搜索第几个字符串,num表示字符串总数,ans表示结果,si表示字符串数组,select表示标志数组
	{
		//System.out.println("n="+n);
		//System.out.println("num="+num);
		if(n==num)
		{
			ans[0]++;
			//System.out.println(ans);//测试到这一步是否正确
			return ;
		}
		
		for(int i=0;i<si[n].length();i++)
		{
			if(select[si[n].charAt(i)-'0']==0)//第n个字符串的第i个字符没被使用过
			{
				select[si[n].charAt(i)-'0']=1;
				
				dfs(n+1,num,ans,si,select);//搜索的第n+1个字符串
				//System.out.println("ans:"+ans);
				select[si[n].charAt(i)-'0']=0;
			}
		}
		
		
	}
	
}//class


发表于 2016-06-15 19:37:16 回复(2)