zoukankan      html  css  js  c++  java
  • 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:
    ",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
    ",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("
    ");
        }
        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:
    ",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
    ",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("
    ");
        }
        return 0;
    }
  • 相关阅读:
    ES6学习之数组扩展
    js三元表达式
    ES6学习之函数扩展
    TS学习之for..of
    TS学习之Symbol
    Visual Studio编译时报错“函数名:重定义;不同的基类型”
    Windows Visual Studio中修改PostgreSQL代码后调试报错
    Windows安装MySQL5.7.17
    289. Game of Life -- In-place计算游戏的下一个状态
    Swift的 convenience && designated init
  • 原文地址:https://www.cnblogs.com/jiangjing/p/3450198.html
Copyright © 2011-2022 走看看