您的位置:首页 > 其它

bzoj 3965: [WF2011]Pyramids

2017-06-14 16:13 309 查看

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
>=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("");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: