DP-MinAbsSum

来源:互联网 发布:sql distinct用法 编辑:程序博客网 时间:2024/05/16 17:34

给定一个数组N个正整数,给每个数一个符号,正或者负使得所有数的的和的绝对值尽可能大。也就是使得这个
val(A, S) = |sum{ A[i]*S[i] for i = 0..N−1 }尽可能大s[i] = +1或者-1。
通过分析可以发现元素的正负不影响结果,问题转化为将数分成两堆,两堆只差最小。首先将元素全部转成正数顺便做了个count sort. 发现这个问题转化为多重背包问题。
DP背包参考http://wenku.baidu.com/view/cf9f0f8ecc22bcd126ff0c73.html

最开始只是将多重背包的代码原样copy过来,将每组数看作重量为i,value为i的物品,背包大小为sum/2。但是时间复杂度为N*N*A不满足要求。原因是背包里没有装东西,参考http://blog.csdn.net/caopengcs/article/details/10028269
将背包中装入达到重量j时剩余i的数量,如果无法达到为-1.

https://codility.com/demo/results/demoH2FANU-T7J/

class Solution {    public int solution(int[] A) {        // write your code in Java SE 8        int[] hash = new int[101];        int max = 0;        int sum = 0;        for(int i=0; i<A.length; i++){            int a=Math.abs(A[i]);            hash[a]++;            sum+=a;            max = Math.max(max,a);        }        //        int half = sum/2+1;        int[] dp = new int[half];        for(int i=0; i<dp.length; i++){            dp[i]=-1;        }        dp[0]=0;        int can=0;        // dp save the left number of item i to achive the sum j        // -1 means sum 0-i < j        for(int i=1; i<=max; i++){            if(hash[i]>0){                for(int j=0; j<dp.length; j++){                    if(dp[j]>=0){                        dp[j]=hash[i];                        if(j>can){                            can = j;                        }                    }                    else{                        if(j-i>=0 && dp[j-i]>0){                            dp[j] = dp[j-i]-1;                            if(j>can){                                can = j;                            }                        }                    }                }            }            if(can>=half) break;        }        return Math.abs(sum-(can<<1));    }}
0 0
原创粉丝点击