zoukankan      html  css  js  c++  java
  • CSU 1536 Bit String Reordering(BFS)

    1536: Bit String Reordering

    Time Limit: 1 Sec  Memory Limit: 256 MB
    Submit: 129  Solved: 45
    [Submit][Status][Web Board]

    Description

     

    Input

     

    Output

     

    Sample Input

    6 3
    1 0 0 1 0 1
    1 3 2

    Sample Output

    1

    HINT

     

    Source

     
     
    这道题当时比赛的时候是用贪心+模拟做的= =
    后来出来听他们说可以状压+BFS做,回来敲一下就1A了
     
    状压+BFS(),就是把每次变化的01串变成一个数字,然后每次交换相邻的两个位置,知道找到最后的结果就输出最小步数
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<ctype.h>
    #include<cstring>
    #include<stdlib.h>
    #include<algorithm>
    using namespace std;
    const int MAXN=20;
    int n,m,result;
    int a[MAXN],temp[MAXN],b[MAXN],vis[1000000];
    struct node
    {
        int res;//01串代表的数字
        int step;//步数
        int num[MAXN];//01串
    }s1,s2;
    queue<node> Q;
    
    int calc(int num[])
    {
        int ans=0,ok=1;
        for(int i=n-1;i>=0;i--)
        {
            ans+=ok*num[i];
            ok*=2;
        }
        return ans;
    }
    
    int BFS()
    {
        node now,next;
        while(!Q.empty())
        {
            now=Q.front();
            Q.pop();
            if(now.res==result) return now.step;
    
            for(int i=0;i<n;i++) next.num[i]=now.num[i];
    
            for(int i=0;i<n-1;i++)
            {
                swap(next.num[i],next.num[i+1]);//交换相邻的两位生成新的01串
                next.res=calc(next.num);
                if(!vis[next.res])
                {
                    vis[next.res]=1;
                    next.step=now.step+1;
                    Q.push(next);
                }
                swap(next.num[i],next.num[i+1]);
            }
        }
    }
    int main()
    {
        scanf("%d %d",&n,&m);
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        for(int i=0;i<m;i++) scanf("%d",&temp[i]);
    
        int cnt=0,flag=1;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<temp[i];j++)
                s1.num[cnt++]=flag;
            flag=!flag;
        }
        s1.res=calc(s1.num);
        s1.step=0;
        Q.push(s1);
        vis[s1.res]=1;//初始化第一个起点串信息
    
        cnt=0,flag=0;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<temp[i];j++)
                s2.num[cnt++]=flag;
            flag=!flag;
        }
        s2.res=calc(s2.num);
        s2.step=0;
        Q.push(s2);
        vis[s2.res]=1;//初始化第二个起点串信息
    
        result=calc(a);
        int ans=BFS();
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    贪心+模拟,就是先生成两个起点01串,然后每次把起点01串和终点01串对比一下,如果发现在相对应的位置的数字不相同的话,就往后找出第一个不相同的数字(比如当前起点串为0终点串为1,那么起点串就要往后面找出第一个1)然后加上两个位置的差距,再比较下一位。   听起来很复杂= =,但是很多代码都是相同的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<stdlib.h>
    #include<algorithm>
    using namespace std;
    const int MAXN=20;
    int a[MAXN],b[MAXN],num[MAXN],temp[MAXN],ans;
    void swap(int &a,int &b)
    {
        int temp;
        temp=a;
        a=b;
        b=temp;
    }
    int min(int a,int b)
    {
        if(a>b) return b;
        else return a;
    }
    int main()
    {
        int n,m,num0=0,num1=0,res1=0,res2=0;
        int minn=0x3f3f3f3f;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==1) num1++;
            if(a[i]==0) num0++;
        }//分别统计终点串01出现的次数
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&temp[i]);
            if(i%2==1) res1+=temp[i];
            if(i%2==0) res2+=temp[i];
        }//这样加的目的是判断起点串第一个数字是放0还是1
        if(res1==num1)
        {
            ans=0;
            memset(b,0,sizeof(b));
            for(int i=1;i<=n;i++) num[i]=a[i];
            int flag=1,cnt=1;
            for(int i=1;i<=m;i++)
            {
                for(int j=1;j<=temp[i];j++)
                    b[cnt++]=flag;
                flag=!flag;
            }//生成起点串
            for(int i=1;i<=n;i++)
            {
                if(num[i]==b[i]) continue;
                else
                {
                    for(int j=i+1;j<=n;j++)
                    {
                        if(b[j]==!b[i])
                        {
                            swap(b[j],b[i]);
                            ans+=j-i;
                            break;
                        }
                    }
                }
            }//贪心找出最近的一个取反位然后加上距离
            minn=min(ans,minn);
        }
        if(res1==num0)
        {
            ans=0;
            memset(b,0,sizeof(b));
            for(int i=1;i<=n;i++) num[i]=a[i];
            int flag=0,cnt=1;
            for(int i=1;i<=m;i++)
            {
                for(int j=1;j<=temp[i];j++)
                    b[cnt++]=flag;
                flag=!flag;
            }
            for(int i=1;i<=n;i++)
            {
                if(num[i]==b[i]) continue;
                else
                {
                    for(int j=i+1;j<=n;j++)
                    {
                        if(b[j]==!b[i])
                        {
                            swap(b[j],b[i]);
                            ans+=j-i;
                            break;
                        }
                    }
                }
            }
            minn=min(ans,minn);
        }
        printf("%d
    ",minn);
        return 0;
    }
    View Code
  • 相关阅读:
    软链接mongo
    添加系统路径
    安装mongodb扩展
    查看php扩展
    查看mongodb状态
    phpExcel 替代 产品, 可导出10W数据,无压力
    饭饭之辈 200 Vue2.0生命周期(组件钩子函数与路由守卫)
    vue 父组件监听子组件事件,emit携带参数,且父组件也自带参数问题
    xlswriter 使用文档,快速写入xls 支持 2007以上的版本
    vue 中组件传值问题
  • 原文地址:https://www.cnblogs.com/clliff/p/4363100.html
Copyright © 2011-2022 走看看