原题链接
http://acm.hdu.edu.cn/showproblem.php?pid=2079
思路:一开始看到有些懵,很像之前做的一道换零钱的题目,但是这里由于具体科目数不知道,所以只能用递归做,然后没头绪上网搜了一下,看到了有人用dfs,就试着写了一下,有了如下代码
package hduoj; import java.util.Scanner; public class hdoj_2079 { private static int kind = 0; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int count = sc.nextInt(); while(count-- != 0){ int score_sum = sc.nextInt(); int k = sc.nextInt(); int[][] data = new int[k][2]; for(int i = 0;i<k;++i){ data[i][0] = sc.nextInt(); data[i][1] = sc.nextInt(); } kind = 0; int[] temp = new int[k]; dfs(score_sum,k,data,temp,0,0); System.out.println(kind); } } private static void dfs(int score_sum,int k,int[][] data,int[] temp,int sum,int index){ if(sum == score_sum){ kind++; return; } if(sum>score_sum||temp[index]>data[index][1]){ return; } for(int i = 0;i<k;++i){ temp[i]++; dfs(score_sum,k,data,temp,sum+data[index][0],i); temp[i]--;//回溯 } } }
然后当然是错的第二组测试数据大了很多,估计是有很多重复数据,因为“同等分数的课没有区别”,而且先选和后选没有区别(就是最终的科目种类一样就算相同的选法,顺序无所谓),然后就去搜了下别人的代码,看到dalao是用外界传入参数来判断遍历所有的科目,然后内部循环控制选课的数量,这样就避免了重复(因为每次选课的数量都唯一,这样就不存在重复),代码如下:
package hduoj; import java.util.Scanner; public class hdoj_2079 { //使用dfs来遍历(普通遍历不行,会有超级多的重复项——需要保证唯一性) private static int kind = 0; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int count = sc.nextInt(); while(count-- != 0){ int score_sum = sc.nextInt(); int k = sc.nextInt(); int[][] data = new int[k][2]; for(int i = 0;i<k;++i){ data[i][0] = sc.nextInt(); data[i][1] = sc.nextInt(); } kind = 0; dfs(score_sum,k,data,0,0); System.out.println(kind); } } private static void dfs(int score_sum,int k,int[][] data,int sum,int index){ if(sum == score_sum){ kind++; return; } if(sum>score_sum||index==k){ return; } for(int i = 0;i<=data[index][1];++i){ dfs(score_sum,k,data,sum+i*data[index][0],index+1); } } }
代码已经ac
希望对大家有所帮助
以上