hdu 1864最大报销额
解法: 01背包问题,dfs也可以。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
double dp[35],ans[35];
double Q,max;
int N,k;
int main()
{
double sum,price,cc,arr[3];
int i,j,flag,m;
char div;
while(~scanf("%lf%d",&Q,&N)&&N!=0)
{
k=0;
for(i=0;i<N;i++)
{
for(j=0;j<3;j++)arr[j]=0;
flag=1;
sum=0;
scanf("%d",&m);
for(j=0;j<m;j++)
{
scanf(" %c:%lf",&div,&price);
if((div=='A'||div=='B'||div=='C'))
{
arr[div-'A']+=price;
}
else flag=0;
}
for(j=0;j<3;j++)
{
sum+=arr[j];
if(arr[j]>600)flag=0;
}
if(sum>1000||sum>Q)flag=0;
if(flag)dp[k++]=sum;
}
cc=max=0;
for(i=0;i<k;i++){
max=0;
for(j=0;j<i;j++){
if(ans[j]+dp[i]<=Q&&max<ans[j]){
max=ans[j];
}
}
ans[i]=max+dp[i];
if(ans[i]>cc)cc=ans[i];
}
printf("%.2lf\n",cc);
}
return 0;
}
hdu 2602 典型的01背包问题:
状态方程 dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
#include<stdio.h>
#include<string.h>
int dp[1010];
int max(int a,int b)
{
return a > b?a:b;
}
int main()
{
int T,i,j,N,V,v;
int num[1010],c[1010];
scanf("%d",&T);
while(T--)
{
memset(num,0,sizeof(num));
memset(c,0,sizeof(c));
memset(dp,0,sizeof(dp));
scanf("%d%d",&N,&V);
for(i=1;i<=N;i++)
scanf("%d",&num[i]);
for(i=1;i<=N;i++)
scanf("%d",&c[i]);
for(i=1;i<=N;i++)
{
for(j=V;j>=0;j--)
{
if(j>=c[i])
dp[j]=max(dp[j],dp[j-c[i]]+num[i]);
}
}
printf("%d\n",dp[V]);
}
return 0;
}
hdu 1203 概率计算问题:
解析: 01背包问题,状态方程 dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
#include<stdio.h>
#include<string.h>
int c[10010];
double w[10010];
double dp[10010];
double max(double a,double b)
{
return a>b?a:b;
}
int main()
{
int a,b,n,m,i,j;
while(~scanf("%d%d",&n,&m)&&(m||n))
{
for(i=1;i<=10010;i++)
dp[i]=0.0;
for(i=1;i<=m;i++)
scanf("%d%lf",&c[i],&w[i]);
for(i=1;i<=m;i++)
for(j=n;j>=0;j--)
if(j>=c[i])
dp[j]=max(dp[j],dp[j-c[i]]+(1-dp[j-c[i]])*w[i]);
a=dp[n]*1000;
b=a%10;
a/=10;
printf("%d.%d%%\n",a,b);
}
return 0;
}
hdu 2955 小偷逃跑问题:
这个题也是01背包问题,不过得需要一些处理技巧=、=,需要把 银行钱款 作为体积,把逃跑的概率作为价值。逃跑的概率计算公式为(1-c[i])*(1-c[j])……
状态方程:dp[j]=max(dp[j],dp[j-w[i]]*c[i]);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int w[105];
double c[105];
double dp[10010];
double max(double a,double b){
return a>b?a:b;
}
int main(){
int T,i,j,n,v;
double p;
scanf("%d",&T);
while(T--){
for(i=0;i<10010;i++)
dp[i]=0;
scanf("%lf%d",&p,&n);
for(v=0,i=1;i<=n;i++){
scanf("%d%lf",&w[i],&c[i]);
v+=w[i];
c[i]=1-c[i];
}
dp[0]=1;
for(i=1;i<=n;i++){
for(j=v;j>=w[i];j--){
if(j>=w[i]){
dp[j]=max(dp[j],dp[j-w[i]]*c[i]);
}
}
}
for(i=v;i>=0;i--)
if((1-dp[i])<=p)
break;
printf("%d\n",i);
}
return 0;
}
poj 2063 利息问题,此题需要一个处理技巧,因为题目中告之,输入数据为1000的倍数,所有可以缩小1000倍,所以最大的债权为1 000 000*(1.1)^40/1000<50000
然后完全背包问题。状态方程:dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int dp[50000];
int c[22],w[22];
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int T,d,n,i,s,j,k,ans;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&s,&d);
scanf("%d",&n);
ans=0;
for(i=1;i<=n;i++)
scanf("%d%d",&c[i],&w[i]),c[i]/=1000;
ans=s;
while(d--)
{
for(i=0;i<50000;i++)dp[i]=0;
for(j=1;j<=n;j++)
{
for(k=c[j];k<=s/1000;k++)
{
dp[k]=max(dp[k],dp[k-c[j]]+w[j]);
}
}
ans+=dp[s/1000];
s=ans;
}
printf("%d\n",ans);
}
return 0;
}
poj 1384
完全背包问题,要求把包必须装满。
一开始把INF设定的小了,导致多次wa……初始化的时候要注意,一开始我初始化成0 了,导致有些数据不行,比如一个c!=0但是p=0的此类数据出错。。。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INF 5000000
int p[505],w[505];
int dp[10010];
int min(int a,int b)
{
return a>b?b:a;
}
int main()
{
int T,i,j,E,F,N,v;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&E,&F);
scanf("%d",&N);
for(i=1;i<=N;i++)
scanf("%d%d",&p[i],&w[i]);
for(i=0;i<10010;i++)dp[i]=INF;
v=F-E;
dp[0]=0;
for(i=1;i<=N;i++)
{
for(j=w[i];j<=v;j++)
{
if(dp[j]==INF)
{
if((dp[j-w[i]]!=INF)||(j==w[i]))dp[j]=dp[j-w[i]]+p[i];
}
else
dp[j]=min(dp[j],dp[j-w[i]]+p[i]);
}
}
if(E!=F&&dp[v]==INF)puts("This is impossible.");
else
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[v]);
}
return 0;
}
poj 2392
多重背包问题,背包的cost 和 weight相同。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct node
{
int h,a,c;
}ndoe;
node arr[405];
int dp[40010];
int max(int a,int b)
{
return a>b?a:b;
}
int cmp(const void *a,const void *b)
{
node aa,bb;
aa=*(node *)a,bb=*(node *)b;
return aa.a-bb.a;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&arr[i].h,&arr[i].a,&arr[i].c);
}
qsort(arr,n,sizeof(node),cmp);
memset(dp,0,sizeof(dp));
dp[0]=1;
int max=0;
for(int i=0;i<n;i++)
{
for(int j=max;j>=0;j--)
{
if(dp[j])
{
for(int k=1;k<=arr[i].c;k++)
{
int temp=j+arr[i].h*k;
if(temp>arr[i].a)break;
else
dp[temp]=1;
if(temp>max)max=temp;
}
}
}
}
printf("%d\n",max);
}
return 0;
}
dp 1276 完全背包问题,和上一个类似,都是weight和value相等。
TLE了一次。RE了2次=、= 没注意,数组越界了。。。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int dp[100010];
int N,cash;
typedef struct node
{
int n,d;
}node;
node arr[15];
int Max(int a,int b)
{
if(a>cash)return b;
if(b>cash)return a;
return a>b?a:b;
}
int cmp(const void *a,const void *b)
{
node aa,bb;
aa=*(node *)a,bb=*(node *)b;
return aa.d-bb.d;
}
int main()
{
int i,j,k,max,temp;
while(~scanf("%d",&cash))
{
scanf("%d",&N);
for(i=0;i<N;i++)
scanf("%d%d",&arr[i].n,&arr[i].d);
memset(dp,0,sizeof(dp));
qsort(arr,N,sizeof(node),cmp);
max=0;
dp[0]=1;
for(i=0;i<N;i++)
{
for(j=max;j>=0;j--)
{
if(dp[j])
{
for(k=0;k<=arr[i].n;k++)
{
temp=j+k*arr[i].d;
max=Max(max,temp);
if(temp<=cash)
dp[temp]=1;
}
}
}
}
printf("%d\n",max);
}
return 0;
}
hdu 2191 多重背包
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int dp[105];
int main()
{
int C,i,j,m,n,p,h,c,v,max;
scanf("%d",&C);
while(C--)
{
scanf("%d%d",&n,&m);
max=0;
memset(dp,0,sizeof(dp));
while(m--)
{
scanf("%d%d%d",&p,&h,&c);
for(i=n;i>=0;i--)
{
for(j=1;j<=c;j++)
{
if(i+j*p<=n)
{
if(dp[i+j*p]<dp[i]+j*h)
dp[i+j*p]=dp[i]+j*h;
if(dp[i+j*p]>max) max = dp[i+j*p];
}
}
}
}
printf("%d\n",max);
}
return 0;
}