标签:
题目大意:
用把一堆数字分为两A、B两堆,一堆m个一堆n个。问A堆数字之和与B堆数字之和的乘积的最大值和最小值
做法:
由于存在负数,(-50,50)我们先把每个数字加上100,dp[i][j]代表用前i个数字凑成j,则状态转移方程为(dp[i][j]=dp[i-1][j-num[k]]。k是1到m+n,枚举k可以得到dp[i][j]的存在情况。最后在解空间里找最大值和最小值
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int dp[55][20010],num[110]; int main() { int n,m; while(~scanf("%d%d",&n,&m)){ int all=n+m; int sum=0; for(int i=1;i<=all;i++){ scanf("%d",&num[i]); sum+=num[i]; num[i]=num[i]+100; } if(n>m){ swap(n,m); } memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=all;i++){ for(int j=min(n,i);j>0;j--){ for(int k=sum+(all)*100;k>=num[i];k--){ if(dp[j-1][k-num[i]]){ dp[j][k]=1; } } } } //cout<<dp[1][1]<<endl; int mini=1e9; int maxi=-1e9; for(int i=0;i<=10000;i++){ if(dp[n][i]){ int x=i-n*100; //cout<<x<<endl; mini=min(mini,x*(sum-x)); maxi=max(maxi,x*(sum-x)); } } printf("%d %d\n",maxi,mini); } return 0; }
标签:
原文地址:http://www.cnblogs.com/Scale-the-heights/p/4423503.html