poj 2923(状态压缩dp)

时间:2022-10-13 08:13:14

题意:就是给了你一些货物的重量,然后给了两辆车一次的载重,让你求出最少的运输次数。

分析:首先要从一辆车入手,搜出所有的一次能够运的所有状态,然后把两辆车的状态进行合并,最后就是解决了,有两种方法:

1.组合解决:

代码实现:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; int n,sum1,sum2,a[];
int st1[],st2[],st[],num1,num2,num;
int total[],all;
//st1数组保存的是第一辆车能够一次运走的所有状态,同理st2数组为第二辆车的
//st数组保存的是两辆车一次能够运走的所有状态
void dfs(int f,int flag,int x,int s)//开始的时候这个dfs是作死的错,说明dfs写得还不够熟练
{
int i,j,temp;
if(flag==&&f==n+)
st1[num1++]=x;
else if(f==n+)
st2[num2++]=x;
if(f>n) return ;
temp=<<(n-f);
if(flag==)
{
if(s+a[f]<=sum1)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
else
{
if(s+a[f]<=sum2)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
} void hebing()//两辆车的状态合并
{
int i,j,t=;
int visited[],temp;
memset(visited,,sizeof(visited));
for(i=;i<num1;i++)
for(j=;j<num2;j++)
{
temp=st1[i]|st2[j];
if(visited[temp]==)
{
st[num++]=temp;
visited[temp]=;
}
}
} void solve(int T)//我这里是用组合解决的,虽然提交了之后发现用组合比用背包时间还少
{ //但是觉得可能是测试数据的原因,个人觉得还是背包靠谱些
printf("Scenario #%d:\n",T);
int temp[],t,res=,x;
int i,j,max=,flag=;
int visited[];
all=;total[]=;
for(i=;i<=n;i++)
max=max+(<<(i-));
while()
{
res++;t=;
memset(visited,,sizeof(visited));
for(i=;i<all;i++)
{
// int kao=0;
//kao++;
for(j=;j<num;j++)
{
x=(total[i]|st[j]);
if(x==max)
{
flag=;
break;
}
if(visited[x]==)
{
visited[x]=;
temp[t++]=x;
}
}
if(flag==)
break;
}
if(flag==)
break;
for(i=;i<t;i++)
total[i]=temp[i];
all=t;
}
printf("%d\n",res);
} int main()
{
int i,T,t;
scanf("%d",&T);
for(t=;t<=T;t++)
{
num1=;
num2=;
num=;
scanf("%d%d%d",&n,&sum1,&sum2);
for(i=; i<=n; i++)
scanf("%d",&a[i]);
dfs(,,,);
dfs(,,,);
hebing();
solve(t);
if(t!=T)
printf("\n");
}
return ;
}

2.背包解决:
代码实现:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; int n,sum1,sum2,a[];
int st1[],st2[],st[],num1,num2,num;
int total[],all; void dfs(int f,int flag,int x,int s)
{
int i,j,temp;
if(flag==&&f==n+)
st1[num1++]=x;
else if(f==n+)
st2[num2++]=x;
if(f>n) return ;
temp=<<(n-f);
if(flag==)
{
if(s+a[f]<=sum1)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
else
{
if(s+a[f]<=sum2)
dfs(f+,flag,x+temp,s+a[f]);
dfs(f+,flag,x,s);
}
} void hebing()
{
int i,j,t=;
int visited[],temp;
memset(visited,,sizeof(visited));
for(i=;i<num1;i++)
for(j=;j<num2;j++)
{
temp=st1[i]|st2[j];
if(visited[temp]==)
{
st[num++]=temp;
visited[temp]=;
}
}
} int Min(int x,int y)
{
return x>y?y:x;
} void solve(int T)
{
printf("Scenario #%d:\n",T);
int i,j,dp[];
for(i=;i<(<<n);i++)
dp[i]=;
dp[]=;
for(i=;i<num;i++)
{
for(j=(<<n)-;j>=;j--)
{
if(dp[j]==)
continue;
if((j&st[i])==)
dp[j|st[i]]=Min(dp[j|st[i]],dp[j]+);
}
}
printf("%d\n",dp[(<<n)-]);
} int main()
{
int i,T,t;
scanf("%d",&T);
for(t=;t<=T;t++)
{
num1=;
num2=;
num=;
scanf("%d%d%d",&n,&sum1,&sum2);
for(i=; i<=n; i++)
scanf("%d",&a[i]);
dfs(,,,);
dfs(,,,);
hebing();
solve(t);
if(t!=T)
printf("\n");
}
return ;
}