ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

如果你有足够的石块,那么建一座金字塔绝不算难事。举个例子,在一块平地上,我们铺一个10*10的矩形,然后在10*10的矩形上面铺一个9*9的,然后8*8的……以此类推,直到顶上1*1。这个金字塔有10层,我们称这类金字塔为“高金字塔”。
如果你认为这样的金字塔太陡了,那么我们有办法让他看上去坡度平缓一些。比如,在10*10的矩形上,我们铺一个8*8的矩形,然后是6*6的……这样的金字塔只有5层了,大约为底座边长的一半。我们称之为“矮金字塔”。
很久以前,一位法老从父亲那儿继承了一大堆用于搭建金字塔的石块。他决定用这些石块搭建一座金字塔——每个石块都必须用上。建筑师告诉他,这样的要求不一定能实现。例如,如果你有10块石头,那么可以搭一个底座为3的矮金字塔;如果有5块石头,那么就搭一个底座为2的高金字塔。如果你有7块石头呢?不幸的是,确实找不出一种搭金字塔的方案了。
思考再三后,法老决定放低要求——搭不止一座金字塔。但是仍然要满足如下几个条件:
1.所有石块都必须用上;
2.金字塔数要尽可能少;
3.所有金字塔两两不同;
4.金字塔至少包含两层,即底座为1的金字塔和底座为2的矮金字塔是不允许的;
5.满足以上4点的基础上,最大的金字塔要尽可能大(大定义为用的石块数多);
6.满足以上5点的基础上,次大的金字塔要尽可能大;
7.以此类推。。
你能求出最好的搭金字塔方案么?或者告诉法老这是做不到的。
金字塔只有300多种,先做一次bitset优化的0-1背包(保证条件1.3.4.),然后对每个询问搜索出条件2.的最优解(处理出哪些n可以用1到3个拼出,其余则只能>=4,用于最优性剪枝),通过搜索顺序保证条件5.6.7.
#include<cstdio>
#include<algorithm>
#include<bitset>
int s1[1007],s2[1007];
struct item{
    int v,a,t;
    bool operator<(item x)const{return v!=x.v?v<x.v:t<x.t;}
}is[327],ps[327],ps1[327];
std::bitset<1000007>f[327];
int ip=0,pp,mf[1000007];
void dfs(int n,int w,int t){
    if(t+mf[n]>=pp)return;
    if(!n){
        pp=t;
        for(int i=0;i<t;++i)ps[i]=ps1[i];
    }
    if(!w)return;
    if(n>=is[w].v&&f[w-1].test(n-is[w].v))ps1[t]=is[w],dfs(n-is[w].v,w-1,t+1);
    dfs(n,w-1,t);
}
int main(){
    s1[1]=s2[1]=1;
    for(int i=2;i<=500;++i){
        s1[i]=s1[i-1]+i*i;
        s2[i]=s2[i-2]+i*i;
    }
    for(int i=2;s1[i]<=1000000;++i)is[++ip]=(item){s1[i],i,1};
    for(int i=3;s2[i]<=1000000;++i)is[++ip]=(item){s2[i],i,0};
    std::sort(is+1,is+ip+1);
    f[0].set(0);
    for(int i=1;i<=ip;++i)f[i]=f[i-1]|f[i-1]<<is[i].v;
    for(int i=1;i<=ip;++i){
        int x=is[i].v;
        if(!mf[x])mf[x]=1;
    }
    for(int i=1;i<=ip;++i){
        for(int j=i+1;j<=ip;++j){
            int x=is[i].v+is[j].v;
            if(x<=1000000&&!mf[x])mf[x]=2;
        }
    }
    for(int i=1;i<=ip;++i){
        for(int j=i+1;j<=ip;++j){
            for(int k=j+1;k<=ip;++k){
                int x=is[i].v+is[j].v+is[k].v;
                if(x<=1000000&&!mf[x])mf[x]=3;
            }
        }
    }
    for(int i=1;i<=1000000;++i)if(!mf[i])mf[i]=4;
    for(int _t=1,n;;++_t){
        if(scanf("%d",&n)!=1||!n)return 0;
        if(!f[ip].test(n))printf("Case %d: impossible\n",_t);
        else{
            printf("Case %d:",_t);
            pp=10000;
            dfs(n,ip,0);
            for(int i=0;i<pp;++i)printf(" %d%c",ps[i].a,"LH"[ps[i].t]);
            puts("");
        }
    }
}

 

posted on 2017-06-14 16:13  nul  阅读(442)  评论(0编辑  收藏  举报