poj 2923(状态压缩dp)

题意:就是给了你一些货物的重量,然后给了两辆车一次的载重,让你求出最少的运输次数。

分析:首先要从一辆车入手,搜出所有的一次能够运的所有状态,然后把两辆车的状态进行合并,最后就是解决了,有两种方法:

1.组合解决:

代码实现:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int n,sum1,sum2,a[15];
int st1[1500],st2[1500],st[1500],num1,num2,num;
int total[1500],all;
//st1数组保存的是第一辆车能够一次运走的所有状态,同理st2数组为第二辆车的
//st数组保存的是两辆车一次能够运走的所有状态
void dfs(int f,int flag,int x,int s)//开始的时候这个dfs是作死的错,说明dfs写得还不够熟练
{
    int i,j,temp;
    if(flag==1&&f==n+1)
        st1[num1++]=x;
    else if(f==n+1)
        st2[num2++]=x;
    if(f>n) return ;
    temp=1<<(n-f);
    if(flag==1)
    {
        if(s+a[f]<=sum1)
         dfs(f+1,flag,x+temp,s+a[f]);
        dfs(f+1,flag,x,s);
    }
    else
    {
        if(s+a[f]<=sum2)
         dfs(f+1,flag,x+temp,s+a[f]);
        dfs(f+1,flag,x,s);
    }
}

void hebing()//两辆车的状态合并
{
    int i,j,t=2;
    int visited[1500],temp;
    memset(visited,0,sizeof(visited));
    for(i=1;i<num1;i++)
     for(j=1;j<num2;j++)
     {
        temp=st1[i]|st2[j];
        if(visited[temp]==0)
        {
           st[num++]=temp;
           visited[temp]=1;
        }
     }
}

void solve(int T)//我这里是用组合解决的,虽然提交了之后发现用组合比用背包时间还少
{                //但是觉得可能是测试数据的原因,个人觉得还是背包靠谱些
    printf("Scenario #%d:\n",T);
    int temp[1500],t,res=0,x;
    int i,j,max=0,flag=0;
    int visited[1500];
    all=2;total[1]=0;
    for(i=1;i<=n;i++)
     max=max+(1<<(i-1));
    while(1)
    {
        res++;t=1;
        memset(visited,0,sizeof(visited));
        for(i=1;i<all;i++)
        {
           // int kao=0;
            //kao++;
            for(j=1;j<num;j++)
            {
                x=(total[i]|st[j]);
                if(x==max)
                {
                    flag=1;
                    break;
                }
                if(visited[x]==0)
                {
                  visited[x]=1;
                  temp[t++]=x;
                }
            }
            if(flag==1)
                break;
        }
        if(flag==1)
         break;
        for(i=1;i<t;i++)
         total[i]=temp[i];
        all=t;
    }
    printf("%d\n",res);
}

int main()
{
    int i,T,t;
    scanf("%d",&T);
    for(t=1;t<=T;t++)
    {
        num1=1;
        num2=1;
        num=1;
        scanf("%d%d%d",&n,&sum1,&sum2);
        for(i=1; i<=n; i++)
         scanf("%d",&a[i]);
        dfs(1,1,0,0);
        dfs(1,2,0,0);
        hebing();
        solve(t);
        if(t!=T)
         printf("\n");
    }
    return 0;
}

2.背包解决:
代码实现:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int n,sum1,sum2,a[15];
int st1[1500],st2[1500],st[1500],num1,num2,num;
int total[1500],all;

void dfs(int f,int flag,int x,int s)
{
    int i,j,temp;
    if(flag==1&&f==n+1)
        st1[num1++]=x;
    else if(f==n+1)
        st2[num2++]=x;
    if(f>n) return ;
    temp=1<<(n-f);
    if(flag==1)
    {
        if(s+a[f]<=sum1)
         dfs(f+1,flag,x+temp,s+a[f]);
        dfs(f+1,flag,x,s);
    }
    else
    {
        if(s+a[f]<=sum2)
         dfs(f+1,flag,x+temp,s+a[f]);
        dfs(f+1,flag,x,s);
    }
}

void hebing()
{
    int i,j,t=2;
    int visited[1500],temp;
    memset(visited,0,sizeof(visited));
    for(i=1;i<num1;i++)
     for(j=1;j<num2;j++)
     {
        temp=st1[i]|st2[j];
        if(visited[temp]==0)
        {
           st[num++]=temp;
           visited[temp]=1;
        }
     }
}

int Min(int x,int y)
{
    return x>y?y:x;
}

void solve(int T)
{
    printf("Scenario #%d:\n",T);
    int i,j,dp[1500];
    for(i=1;i<(1<<n);i++)
     dp[i]=100000000;
    dp[0]=0;
    for(i=1;i<num;i++)
    {
        for(j=(1<<n)-1;j>=0;j--)
        {
            if(dp[j]==100000000)
             continue;
            if((j&st[i])==0)
             dp[j|st[i]]=Min(dp[j|st[i]],dp[j]+1);
        }
    }
    printf("%d\n",dp[(1<<n)-1]);
}

int main()
{
    int i,T,t;
    scanf("%d",&T);
    for(t=1;t<=T;t++)
    {
        num1=1;
        num2=1;
        num=1;
        scanf("%d%d%d",&n,&sum1,&sum2);
        for(i=1; i<=n; i++)
         scanf("%d",&a[i]);
        dfs(1,1,0,0);
        dfs(1,2,0,0);
        hebing();
        solve(t);
        if(t!=T)
         printf("\n");
    }
    return 0;
}

 

 

转载于:https://www.cnblogs.com/jiangjing/p/3450198.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值