题目 
   
主要思路 
首先,上来第一眼看是一个很简单的排列组合问题,但是暴力算法肯定是超时的。废话不多说,上代码。  
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class Main {
	
	public static void main(String[] args) 
	{
		Scanner in =new Scanner(System.in);
		int N,i,temp,tt;
		N=in.nextInt();        
		int[] num=new int[N];
		for ( i = 0; i < N; i++) 
			num[i]=in.nextInt();
		Set<Integer> contain =new HashSet<>();
		List<Integer> a =new LinkedList<>();        
		contain.add(Integer.valueOf(num[0]));     
		for(i=1;i<N;i++)
		{
			for (Iterator<Integer> iter =contain.iterator();iter.hasNext();) {
				tt=iter.next().intValue();
				temp=tt+num[i];
				if(temp!=0&&temp<100000&&!contain.contains(Integer.valueOf(temp)))
					a.add(Integer.valueOf(temp));
				temp=tt-num[i];
				temp=Math.abs(temp);   
				if(temp!=0&&temp<100000&&!contain.contains(Integer.valueOf(temp))&&!a.contains(Integer.valueOf(temp)))
						a.add(Integer.valueOf(temp));
			}
			contain.addAll(a);
			a.clear();
			if(!contain.contains(Integer.valueOf(num[i])))
				contain.add(Integer.valueOf(num[i]));
		}
		System.out.println(contain.size());
	}
}
  
 
 记录一下自己第一次全部AC,可能有更好的思路,但是下面还是讲一下我的思路吧!  
  
思路 
首先,对于这种需要很多组合的问题,肯定是动态规划了。首先将第一个砝码放入右边,目前只有一种组合。继续放入第二个砝码,你可以选择继续放到右边或者左边。放入右边其实逻辑上就是砝码A+砝码B,放入左边就是砝码A-砝码B结果的绝对值。剩下的就是重复一直放入砝码。  在代码实现中,我选择的数据结构是HashSet和LinkedList。HashSet用于存放加完砝码的结果。而LinkedList用于存放加砝码时的不确定砝码值。  为什么不直接将加完的值全放进HashSet中,非得加一个LinkedList。因为如果直接加入,那么就对上一次的砝码称重的结果,造成了影响。意思就是,你刚加出来的结果,有会被踢出去,被这个重量的砝码再运算一次。  例如:  
 
 HashSet : 1 2 4  
  
这次要加入的砝码是 6  首先1 + 6 = 7  
 
 那么HashSet: 1 2 4 7  
  
到最后 7 + 6 = 13  
 
 HashSet: 1 2 4 7 13  
  
实际上,这里的6用了两次,你把用这次砝码6运算出来的结果7,又加了一次6,变成了13.显然,这个结果是错误的。  我选择将一次迭代的结果,先放在LinkedList容器中,最终一并放入HashSet中.  
第二次代码 
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class Main {
	
	public static void main(String[] args) 
	{
		Scanner in =new Scanner(System.in);
		int N,i,temp,tt;
		N=in.nextInt();        
		int[] num=new int[N];
		for ( i = 0; i < N; i++) 
			num[i]=in.nextInt();
		Set<Integer> contain =new HashSet<>();
		Set<Integer> a =new HashSet<>();        
		contain.add(Integer.valueOf(num[0]));     
		for(i=1;i<N;i++)
		{
			for (Iterator<Integer> iter =contain.iterator();iter.hasNext();) {
				tt=iter.next().intValue();
				temp=tt+num[i];
				if(temp!=0&&temp<100000)
					a.add(Integer.valueOf(temp));
				temp=tt-num[i];
				temp=Math.abs(temp);
				if(temp!=0&&temp<100000)
						a.add(Integer.valueOf(temp));
			}
			contain.addAll(a);
			a.clear();
			if(!contain.contains(Integer.valueOf(num[i])))
				contain.add(Integer.valueOf(num[i]));
		}
		System.out.println(contain.size());
	}
}
  
最新的改进:  很明显if语句中的限制条件变少了。因为我运用HashSet的性质,无序、不可重复。使用两个HashSet,每次运算的结果。不用再判断在原来出现过!直接将所以的结果都加入,如果重复会直接加入失败。  第一版本的代码是用contains( )方法去判断,是否在原来的容器中出现,HashSet对于查找效率很高,使用HashSet直接添加,他会先查找是否先前存在该值,明显的HashSet查找的效率会快于contains( )方法。  
   全部AC的感觉太棒了!!! 
                
                
                
        
    
 
 |