poj 1948 二维01背包

来源:互联网 发布:淘宝客活动广场有用吗 编辑:程序博客网 时间:2024/06/05 08:59
题意:给你n个小棒(l<=40,n<=40),问你全用光它能拼成的最大的面积。
思路:40个小棒,每个40,最长1600,每个边都不会比半周长长,所以是800,
设dp[i][k][j],分别是40,800,800,意思就是用了前i个小棒能组成的两个边为k和j,能为1.不能为0;
dp[0][0][0] = true;
for (i = 1; i <= n; i++)
   for (j = 0; j <= bound; j++)
    for (k = 0; k <= bound; k++)
     dp[i][j][k] = dp[i-1][j][k] | (len[i] <= j && dp[i-1][j-len[i]][k])
      | (len[i] <= k && dp[i-1][j][k-len[i]]);
降一维,这里要注意的是:
//这里的条件应该是》=0,而不是a[i],因为这是两个背包,j大于a[i],k小于a[i]或者反过来是可以的,
 //如果是》>=a[i]的话,那么上述情况就会被舍弃了。
for(int i=1; i<=n; i++)
    {
            for(int j=m;j>=0;j--){
                for(int k=m;k>=0;k--){
                    if(j>=a[i]&&dp[j-a[i]][k]){
                            dp[j][k]=1;
                    }
                    if(k>=a[i]&&dp[j][k-a[i]]){
                        dp[j][k]=1;
                    }
                }
            }
    }
然后对三条边用海伦公式搞一下就好了
#include<iostream>#include<stdlib.h>#include<string.h>#include<algorithm>#include<stdio.h>#include<cmath>using namespace std;int dp[1600][1600];//表示三角形的两条边分别是i与j,值为1就是有这三条边,值为0就是没有这三条边int n;int a[50];int sum;int cal(double a,double b,double c){    if((a+b<c)||(a+c<b)||(b+c<a))    {        return -1;    }    double ans=(a+b+c)/2.0;    ans=sqrt(ans*(ans-a)*(ans-b)*(ans-c));    return (int)(ans*100);}int main(){    scanf("%d",&n);    sum=0;    int m;    for(int i=1; i<=n; i++)    {        scanf("%d",&a[i]);        sum+=a[i];    }    m=sum/2;    memset(dp,0,sizeof(dp));    dp[0][0]=1;    for(int i=1; i<=n; i++)    {            for(int j=m;j>=0;j--){//这里的条件应该是》=0,而不是a[i],因为这是两个背包,j大于a[i],k小于a[i]或者反过来是可以的,                    //如果是》>=a[i]的话,那么上述情况就会被舍弃了。                for(int k=m;k>=0;k--){                    if(j>=a[i]&&dp[j-a[i]][k]){                            dp[j][k]=1;                    }                    if(k>=a[i]&&dp[j][k-a[i]]){                        dp[j][k]=1;                    }                }            }    }    int ans;    int answer=0;    for(int i=1; i<=m; i++)    {        for(int j=1; j<=m; j++)        {            if(dp[i][j]==1)            {                ans=cal(i,j,sum-i-j);                answer=max(answer,ans);            }        }    }    printf("%d\n",answer==0?-1:answer);    return 0;}

0 0
原创粉丝点击