poj 2923 Relocation 【状压DP】

题目链接:http://poj.org/problem?id=2923



题目大意:有两辆车和n个货物,每个货物有自己的重量,
                 车子有承载重量,问把货物全部拉走最少需要车子来回跑几趟;
 

思路:因为n<=10,所以可以状态压缩,总状态量为 1<<n,写个判断函数,把每种可以一次运走的状态储存,
           然后就是DP,dp[j|state[i]]=min(dp[j|state[i]],dp[j]+1);

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const ll mod=1e9+7;
const int N=1e3+30;

int dp[N];
int vis[N],w[12];
int e,a,b,n,state[N];

int judge(int x)//判断该状态是否符合条件
{
    int sum=0;
    memset(vis,0,sizeof(vis));
    vis[0]=1;//能装下的重量标记为1
    for(int i=0;i<n;i++)
    {
        if((x>>i)&1)
        {
            sum+=w[i];
            for(int j=a;j>=w[i];j--)
            {//这里可以模拟一下,列入a=7,w[1]=5,w[2]=3,w[3]=2,自行模拟
                if(vis[j-w[i]])
                    vis[j]=1;
            }
        }
    }
    if(a+b<sum) return 0;
    for(int i=0;i<=a;i++)
    {//就算sum<a+b,也不一定满足条件,需要再判断
        if(vis[i]&&sum-i<=b)
            return 1;
    }
    return 0;
}

void init()
{
    e=0;
    for(int i=1;i<(1<<n);i++)
    {
        dp[i]=inf;//初始化
        if(judge(i))
            state[e++]=i;//可以一次运走的状态
    }
}

int main()
{
    int T,cas=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d",&n,&a,&b);
        for(int i=0;i<n;i++)
            scanf("%d",&w[i]);
        init();
        dp[0]=0;
        for(int i=0;i<e;i++)//dp找出最小花费
        {
            for(int j=(1<<n)-1;j>=0;j--)
            {
                if(dp[j]==inf) continue;
                if((j&state[i])==0)
                    dp[j|state[i]]=min(dp[j|state[i]],dp[j]+1);
            }
        }
        printf("Scenario #%d:\n%d\n\n",++cas,dp[(1<<n)-1]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41984014/article/details/88035190