背包

01背包



hdu2955 Robberies

需要找到背包的容量。

有两个选择

1.能获得的最大金额

                每个银行价值≤100,最多100家银行,所以能获得的最大金额为10000(不考虑风险)

               int  v[10000] ;

2.逃脱的概率。

                最终逃脱的概率为在每一个银行都不被抓,即所有的逃脱概率(1-P[i])相乘。

                把概率放大一百倍之后作为背包容量?


以金额作为背包,概率作为价值。满足dp[i]>=P的最后一个元素的下标就是答案


[cpp] view plain copy
  1. #include<iostream>  
  2. using namespace std;  
  3.   
  4. double dp[10000];  
  5.   
  6. int main()  
  7. {  
  8.     int T,N,i,j,v[105],sum;  
  9.     double P,p[105];  
  10.     scanf("%d",&T);  
  11.     while(T--)  
  12.     {  
  13.         scanf("%lf%d",&P,&N);P=1-P;  
  14.         for(sum=0,i=1;i<=N;i++)  
  15.         {  
  16.             scanf("%d%lf",&v[i],&p[i]);  
  17.             p[i]=1-p[i];  
  18.             sum+=v[i];  
  19.         }  
  20.           
  21.         for(i=1;i<=sum;i++)  dp[i]=-1.0;dp[0]=1;//由于有的逃脱概率等于0,所以初始化不能为0,  
  22.           
  23.         for(i=1;i<=N;i++)  
  24.         {  
  25.             //printf("i=%d v=%d p=%.2lf dp[i-v[i]]*p[i]")  
  26.             for(j=sum;j>=v[i];j--)  
  27.             {  
  28.                 if(dp[j]<dp[j-v[i]]*p[i]&&dp[j-v[i]]!=-1)  
  29.                     dp[j]=dp[j-v[i]]*p[i];  
  30.             }  
  31.         //  for(j=0;j<=sum;j++)  
  32.         //  printf("%.2lf ",dp[j]);printf("\n");  
  33.         }  
  34.           
  35.         for(i=sum;i>=0;i--)  
  36.         {  
  37.         //  printf("------%.2lf\n",dp[i]);  
  38.             if(dp[i]>=P)  
  39.             {  
  40.                 printf("%d\n",i);  
  41.                 break;  
  42.             }  
  43.         }  
  44.     }  
  45.       
  46.       
  47.     return 0;  


多重背包


二进制优化

#include<stdio.h>

int main()
{
	int N,n,sum;
	while(scanf("%d",&N),N)
	{
		n=1,sum=0;
		
		while(n<=N/2)
		{
			printf("%d ",n);
			sum+=n;                    //为最后一个数字做准备 
			n*=2;                      //double
		}
		n=N-sum;
		printf("%d\n",n);
	}
	return 0;
}




hdu2844


给出N种物品,第i种有n[i]个,体积为v[i]

用这些物品能组成多少种体积(即题目中的价格)


#include<iostream>
using namespace std;

int dp[100001],v[101],n[101];

int main()
{
	int N,M,num,sum,i,j;
	while(scanf("%d%d",&N,&M),N+M)
	{
		
		for(i=1;i<=N;i++)	scanf("%d",&v[i]);
		for(i=1;i<=N;i++)	scanf("%d",&n[i]);
		memset(dp,0,sizeof(dp));
		
		for(i=1;i<=N;i++)
		{
			sum=0,num=1;
			while(num<=n[i]/2)
			{
				for(j=M;j>=num*v[i];j--)
				{
					if(dp[j]<dp[j-num*v[i]]+v[i]*num)
						dp[j]=dp[j-num*v[i]]+v[i]*num;
				}
				sum+=num;
				num*=2;
			}
			num=n[i]-sum;
			for(j=M;j>=num*v[i];j--)
			{
				if(dp[j]<dp[j-num*v[i]]+v[i]*num)
					dp[j]=dp[j-num*v[i]]+v[i]*num;
			}
		}
		
		
		for(sum=0,i=1;i<=M;i++)
			if(dp[i]==i)	sum++;
		printf("%d\n",sum);
	}
	return 0;
}


hdu2191


#include<iostream>
using namespace std;

int main()
{
	int T,N,M,dp[101],v[101],p[101],n[101],i,j,num,sum;
	
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&N,&M);
		
		
		memset(dp,0,sizeof(dp));
		
		for(i=1;i<=M;i++)
		{
			scanf("%d%d%d",&v[i],&p[i],&n[i]);
			
			num=1,sum=0;
			while(num<=n[i]/2)
			{
				for(j=N;j>=num*v[i];j--)
				{
					if(dp[j]<dp[j-num*v[i]]+num*p[i])
						dp[j]=dp[j-num*v[i]]+num*p[i];
				}
				sum+=num;num*=2;
			}
			num=n[i]-sum;
			for(j=N;j>=num*v[i];j--)
			{
				if(dp[j]<dp[j-num*v[i]]+num*p[i])
					dp[j]=dp[j-num*v[i]]+num*p[i];
			}
		}
		printf("%d\n",dp[N]);
	}
	return 0;
}


二维背包


hdu3496

其中一维必须刚好装满

注意初始化


#include<stdio.h>
#include<string.h>
int dp[1001][101],v,p;

int main()
{
	int i,j,k,m,n,l,T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d%d",&n,&m,&l);
		for(i=0;i<=l;i++)
			for(j=0;j<=m;j++)
				dp[i][j]=-999999999;
		for(i=0;i<=l;i++)	dp[i][0]=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&v,&p);
			for(k=m;k>=1;k--)
				for(j=l;j>=v;j--)
					if(dp[j][k]<dp[j-v][k-1]+p)
						dp[j][k]=dp[j-v][k-1]+p;
		}
		if(dp[l][m]>0)	printf("%d\n",dp[l][m]);
		else	printf("0\n");
	}
	return 0;
}







你可能感兴趣的:(背包)