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;
}
原文地址:https://www.cnblogs.com/bitch1319453/p/5011452.html