Relocation POJ-2923

来源:互联网 发布:为什么打开软件会闪退 编辑:程序博客网 时间:2024/04/29 07:03
题目链接
题目意思: 有 n 个货物,并且知道了每个货物的重量,每次用载重量分别为c1,c2的火车装载,问最少需要运送多少次可以将货物运完。
分析:本题可以用二进制枚举所有不冲突的方案,再来dp 一下,一开始dp数组初始化为正无穷,dp[0]=0,代表什么都不运送需要多少趟,对于每个不冲突的选择方案;假设有 5 个物品, 就是更新 dp 数组 00000~11111 的状态的趟数。每次需要用不冲突的方案来更新 dp 数组,如果不冲突的方案 与 上一个状态不冲突 就可以转,值为 上一个状态的值+1。
如果值小则更新值,最后 dp [11111]   就是最终答案.
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define Max (1<<15)using namespace std;const int inf=0x3f3f3f3f;int s[11],dp[Max],s1[Max],s2[Max],dis[Max];int main (void){    int t,n,c1,c2,i,j,k,l1,l2,L,cas=1;    scanf("%d",&t);    while(t--&&scanf("%d%d%d",&n,&c1,&c2))    {        for(i=0; i<n; i++)            scanf("%d",&s[i]);        l1=l2=0;        for(i=0; i<(1<<n); i++)        {            k=0;            for(j=0; j<n; j++)                if(i&(1<<j))                    k+=s[j];            if(k<=c1)s1[l1++]=i;            if(k<=c2)s2[l2++]=i;        }        L=0;        for(i=0; i<l1; i++)            for(j=0; j<l2; j++)                if((s1[i]&s2[j])==0)                    dis[L++]=(s1[i]|s2[j]);        memset(dp,inf,sizeof(dp));        dp[0]=0;        for(int i=0; i<L; i++) //????????????.            for(int j=0;j<(1<<n); j++)            {                if(j&dis[i]||dp[j]==inf) continue;                dp[j|dis[i]]=min(dp[j|dis[i]],dp[j]+1);            }        printf("Scenario #%d:\n%d\n\n",cas++,dp[(1<<n)-1]);    }    return 0;}




0 0
原创粉丝点击