状态压缩DP-Most Powerful(POJ 3471)

Most Powerful


Time Limit: 2 Seconds      Memory Limit: 65536 KB


Recently, researchers on Mars havediscovered N powerful atoms. All of them are different. These atoms have someproperties. When two of these atoms collide, one of them disappears and a lotof power is produced. Researchers know the way every two atoms perform whencollided and the power every two atoms can produce.

You are to write a program to make it mostpowerful, which means that the sum of power produced during all the collides ismaximal.

Input

There are multiple cases. The first lineof each case has an integer N (2 <= N <= 10), which means there are Natoms: A1, A2, ... , AN. Then N lines follow.There are N integers in each line. The j-th integer on the i-th line is thepower produced when Aiand Aj collide with Aj gone.All integers are positive and not larger than 10000.

The last case is followed by a 0 in oneline.

There will be no more than 500 casesincluding no more than 50 large cases that N is 10.

Output

Output the maximal power these N atoms canproduce in a line for each case.

Sample Input

2
0 4
1 0
3
0 20 1
12 0 1
1 10 0
0

Sample Output

4
22

【题目大意】:就是说有N中气体,每种气体相碰(有主动和被动碰撞的,且释放的能量不一样)都会释放能量,同时被碰撞的的气体会消失,每两个气体都能相碰;

【分析】这道题还是相当简单的,其实dp只需要是一维数组,因为记录最后被碰撞的元素,仅仅是记录当前的状态即可;

【状态方程】dp[state],表示当前已经消失的气体的状态,值为最大能量值

【状态转移方程】dp[state] = dp[state’]+value[i][j](j消失了哈);

【状态边界】dp[1<<i],(0<=i<=N);

Java代码如下

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	private int dp[];
	private int value[][];
	public Main(int N){
		
		dp = new int[1<<N];
		value = new int[N][N];
		
		Arrays.fill(dp, 0);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner cin = new Scanner(System.in);
		int N =cin.nextInt();
		Main ma ;
	
		while(N != 0){
			ma = new Main(N);
			
			for(int i = 0;i<N;i++){
				for(int j = 0;j<N;j++){
					ma.value[i][j] = cin.nextInt();
				}
			}
			
			System.out.println(ma.getMaxEnergy());
			N =cin.nextInt();
		}
		
	}
	int max =0;
	private int getMaxEnergy() {
		// TODO Auto-generated method stub
	
		//因为状态时不断增大的,所以放大最外层循环;
		for(int s=0;s<dp.length;s++){
			//i表示主动去碰撞别人的,j表示被碰撞的;
			for(int i=0;i<value.length;i++){
				if((s & (1<<i)) != 0){
					continue;
				}
				for(int j=0;j<value.length;j++){
					if(i == j){
						continue;
					}
					
					if((s & (1<<j)) != 0){
						continue;
					}
				
					
					dp[s|(1<<j)] = Math.max(dp[s|(1<<j)] ,dp[s]+value[i][j]);
					max = Math.max(max, dp[s|(1<<j)]);
				}
			}
		}
		return max;
	}

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值