poj2923 状压记忆化搜索

来源:互联网 发布:lvs和nginx的区别 编辑:程序博客网 时间:2024/05/01 01:15

题意: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;}

0 0
原创粉丝点击