COCI 2016/2017 Round 4 C dp

Kile and Pogi have found N​ banknotes on the street. After making sure that the original owneris nowhere to be found, they decided to split the banknotes amongst themselves.In the end they want to “win” the same amount of money so they split thebanknotes in such a way. Of course, the sum of the banknotes nobody ends uphaving is ​the least possible​one.

 

Since they couldn’t justleave the remaining banknotes on the street, they decided to go to a nearbycasino and put everything on ​red​, hoping that theywould end up getting twice the money they bet. The roulette decided on the(lucky, for this time) number 13 and our heroes decided to split the money theywon. The payout is such that Kile and Pogi will always be able to split themoney they won into two equal parts.

 

Because of the immense adrenaline rush, theboys have lost their mathematical abilities. Help them figure out how muchmoney each of them is taking home.

 

INPUT

 

The first line of input contains theinteger ​ ​      ​N (1 ≤ ​N ≤ 500) that denotes the number of banknotes on the street.

Each of thefollowing th     N​ lines contains a single positive integer ​​  ci that denotes the value of ​  the ​i banknote in kunas (kn). The total sum of money will not exceed 100000 kn. 

 

OUTPUT

 

You must output the amount of money each of them took home.

 

SCORING

 

In test cases worth 50 points total, ​    ​N will be less than orequal to 13.

In test cases worth 70 points total, ​    ​N will be less than orequal to 50, and the total sum of money will be at most 1000 kn.

 

SAMPLE TESTS

 

input

2 3 1 6


6

2 3 5 8 13


output

6


18


题意:给你n个数  求出一个最大的m  使得n个数能组成2个m  求sum-m


题解:定义dp[i][j]为前i个数  差为j  组成2个m的数目前最大的那个是多少


#include
#include
#include
#include
using namespace std;
int dp[505][100005],a[505];
int main(){
    int n,i,j,sum=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    memset(dp,-1,sizeof(dp));
    dp[0][0]=0;
    for(i=1;i<=n;i++){
        for(j=0;j<=sum/2;j++){
            if(dp[i-1][j]!=-1)dp[i][j+a[i]]=max(dp[i-1][j]+a[i],dp[i][j+a[i]]);
            dp[i][j]=max(dp[i-1][j],dp[i][j]);
            if(j-a[i]<0){
                if(dp[i-1][j]!=-1)dp[i][abs(j-a[i])]=max(dp[i][abs(j-a[i])],dp[i-1][j]+abs(j-a[i]));
            }
            else{
                if(dp[i-1][j]!=-1)dp[i][j-a[i]]=max(dp[i-1][j],dp[i][j-a[i]]);
            }
        }
    }
    printf("%d\n",sum-dp[n][0]);
    return 0;
}


你可能感兴趣的:(dp)