题意:n个货物,第i个重量为Wi,有两只船,载重分别为C1,C2。问至少需要两艘船运几趟才能将n个货物运完。
解法:由于n小于等于10,可以联想到状态压缩。求出两艘船一次可以运送的状态(将两个船分别一次可以运送的状态取 ‘或’ 就可以了)。然后就是常规的记忆化搜索。
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int workable1[2100];
int p1;
int workable2[2100];
int p2;
bool tool[2100];
int workable[2100];
int p;
int n;
int num[12];
int ship1,ship2;
int ans[2100];
int weight(int k)
{
int out=0;
for(int i=0;i<n;i++)
if(k&(1<<i))
out+=num[i];
return out;
}
int dp(int k)
{
if(ans[k]!=-1)
return ans[k];
int out=100;
for(int i=0;i<p;i++)
if((k&workable[i])==workable[i])
out=min(out,dp(k-workable[i])+1);//cout<<dp(k-workable[i])+1;
return ans[k]=out;
}
int main()
{
int t;cin>>t;int an=1;
while(t--)
{
p1=0,p2=0,p=0;
memset(tool,0,sizeof tool);
memset(ans,-1,sizeof ans);ans[0]=0;
scanf("%d%d%d",&n,&ship1,&ship2);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
for(int i=0;i<(1<<n);i++){
if(weight(i)<=ship1)
workable1[p1++]=i;
}
for(int i=0;i<(1<<n);i++){
if(weight(i)<=ship2)
workable2[p2++]=i;
}
for(int i=0;i<p1;i++)
for(int j=0;j<p2;j++)
tool[workable1[i]|workable2[j]]=1;
for(int i=1;i<(1<<n);i++)
if(tool[i]) workable[p++]=i,ans[i]=1;
printf("Scenario #%d:\n",an++);
cout<<dp((1<<n)-1)<<"\n\n";
}
return 0;
}