• uva1377 ruler


    Ruler 

    给你一系列的长度。你要制作一个有m个刻度的尺子,使得任意一个长度都能以某两个刻度之间的距离表示

    要求m尽量小的前提下尺子长度尽量小。你可以认为刻度数不超过7

    首先要想明白的一点,尺子长度就为这n个长度中的最大值。以这个值为长度的尺子一定能满足m尽量小。

    然后我们如何去搜索呢?我们的刻度是任意的,但可以跟给定长度建立关系。我们枚举一个当前还不能表示的长度,然后枚举这个长度是由哪个已有刻度和新刻度共同产生的。这样的做法是显然能得到解的。还有一个重要问题,如何判重呢?我们只要判断当前状态能表示哪些刻度就有了——即表示的给定长度都相同的两种状态视为同一种状态。其中的原因可以这么想。因为枚举刻度的时候我们确定了左端点和右端点,即0和尺子的最大刻度。

    然后这样对广搜判重的时候就有两种情况

    1.当前得到的状态消耗刻度数比相同状态的所用刻度数多

    这种情况不必多说,说明当前的刻度划分方式是不明智的一种,显然应该舍弃之。

    2.当前得到的状态消耗刻度数和相同状态的所有刻度数一样多

    因为左右端点确定,若他们表示的状态都相同,要么这两个尺子相同,要么这二者之间就类似是对称的。即在搜索中是可以类似进行操作的

    来的渣比我讨论吧。。。参考别人才写的

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<queue>
    using namespace std;
    const int maxm=58;
    const int maxn=1000008;
    int a[maxm];
    int b[maxm];
    int idx;
    set<int>    ans;
    int shit[maxn];
    bool vis[maxn<<5];
    struct fuck{
        int state;
        set<int>    ans;
    }f;
    void bfs()
    {
        queue<fuck>    q;
        f.ans.clear();f.ans.insert(0);f.state=0;
        q.push(f);
        int i;
        while(!q.empty())
        {
            f=q.front();q.pop();
        //    printf("%d
    ",f.state);
            if(f.state==(1<<idx)-1)
            {
                if(ans.size()==0)
                    ans=f.ans;
                else
                {
                    if(ans.size()<f.ans.size())    return;
                    else    if(ans.size()>f.ans.size())    ans=f.ans;
                /*    else
                    {
                        if(*ans.rbegin()>*f.ans.rbegin())
                            ans=f.ans;
                    }*/
                }
            }
            if(f.ans.size()==7)    continue;
            for(i=0;i<idx;i++)
            {
                if(f.state&(1<<i))    continue;
                for(set<int>::iterator it =f.ans.begin();
                    it!=f.ans.end();it++) 
                {
                //    printf("%dbitch
    ",*it);
                    if(*it>b[i])
                    {
                        fuck p=f;
                        int sum=*it-b[i];
                        for(set<int> :: iterator it2=f.ans.begin();
                        it2!=f.ans.end();it2++)
                        {
                            int nu=abs(*it2-sum);
                        //    printf("bitch%d
    ",nu); 
                            if(shit[nu]==-1)    continue;
                            p.state=(p.state|(1<<shit[nu]));
                        }
                        p.ans.insert(sum);
                        if(!vis[p.state])
                        {
                            q.push(p);
                            vis[p.state]=true;
                        }
                    }
                    if(*it+b[i]<=b[idx-1])
                    {
                        fuck p=f;
                        int sum=*it+b[i];
                        for(set<int> :: iterator it2=f.ans.begin();
                        it2!=f.ans.end();it2++)
                        {
                            int nu=abs(*it2-sum);
                            if(shit[nu]==-1)    continue;
                            p.state=(p.state|(1<<shit[nu]));
                        }
                        p.ans.insert(sum);
                        if(!vis[p.state])
                        {
                            q.push(p);
                            vis[p.state]=true;
                        }
                    }    
                }
            }
        }
    }
    int main()
    {
        int i,j,n,m;
        int cas=1;
        while(scanf("%d",&n)==1&&n)
        {
            for(i=1;i<=n;i++)
                scanf("%d",&a[i]);
            sort(a+1,a+1+n);
            idx=0;
            memset(vis,false,sizeof(vis));
            memset(shit,-1,sizeof(shit));
            ans.clear();
            for(i=1;i<=n;i++)
            {
                if(shit[a[i]]!=-1)    continue;
                b[idx++]=a[i];
                shit[a[i]]=i;
            }
            for(i=0;i<idx;i++)
                shit[b[i]]=i;
        //    for(i=0;i<idx;i++)    printf("%d ",b[i]);printf("
    ");
            bfs();
            set<int>    ::iterator it;
            bool flag=false;
            printf("Case %d:
    ",cas++);
            printf("%d
    ",ans.size());
            for(it=ans.begin();it!=ans.end();it++)
            {
                if(flag)    printf(" ");
                printf("%d",*it);
                flag=true;
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    Digital image processing In C#
    C#数字图像处理(摘录)
    C# P/Invoke中传递数组参数
    字符常用方法(c#)——(待扩展)
    java监控多个线程的实现
    jdbc访问数据库
    java与MSSQL2000连接
    java下的日期函数实现
    MyEclipse中防止代码格式化时出现换行的情况的设置
    java InputStream读取数据问题
  • 原文地址:https://www.cnblogs.com/bitch1319453/p/5011452.html
Copyright © 2020-2023  润新知