这个是一道状压dp,先预处理出所有可以一次运输的状态,然后在转移就可以了。
然而还是有一个地方要注意,两个符号是判断,一个符号是位运算orz....
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
bool flag[10010];
int q[4][10010],tail[4],c[4],dp[10010],a[10010],n;
void clean()
{
memset(q,0,sizeof(q));
memset(flag,0,sizeof(flag));
memset(dp,127,sizeof(dp));
memset(c,0,sizeof(c));
memset(tail,0,sizeof(tail));
dp[0]=0;tail[1]=1;tail[2]=1;
q[1][1]=0;q[2][1]=0;
}
bool check(int x,int w)
{
int xx=1,tot_v=0;
while ((1<<(xx-1))<=w)
{
if ((1<<(xx-1)&w)!=0)
tot_v+=a[xx];
xx++;
}
if (tot_v<=c[x]) return true;
return false;
}
int main()
{
int ci;
scanf("%d",&ci);
for (int t=1;t<=ci;t++)
{
printf("Scenario #%d:\n",t);
clean();
scanf("%d%d%d",&n,&c[1],&c[2]);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=(1<<n)-1;i++)
{
if (check(1,i)) q[1][++tail[1]]=i;
if (check(2,i)) q[2][++tail[2]]=i;
}
for (int i=1;i<=tail[1];i++)
for (int j=1;j<=tail[2];j++)
if ((q[1][i]&q[2][j])==0)
flag[q[1][i]|q[2][j]]=true;
for (int i=0;i<=(1<<n)-1;i++)
{
i=i;
for (int j=0;j<=(1<<n)-1;j++)
if ((flag[j])&&((i|j)==i))
dp[i]=min(dp[i],dp[i-j]+1);
}
printf("%d\n",dp[(1<<n)-1]);
printf("\n");
}
}
然而读题依旧是个大问题。。。。