衡阳市八中day2修正版solution.docx

上传人:b****7 文档编号:10543481 上传时间:2023-02-21 格式:DOCX 页数:14 大小:73.65KB
下载 相关 举报
衡阳市八中day2修正版solution.docx_第1页
第1页 / 共14页
衡阳市八中day2修正版solution.docx_第2页
第2页 / 共14页
衡阳市八中day2修正版solution.docx_第3页
第3页 / 共14页
衡阳市八中day2修正版solution.docx_第4页
第4页 / 共14页
衡阳市八中day2修正版solution.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

衡阳市八中day2修正版solution.docx

《衡阳市八中day2修正版solution.docx》由会员分享,可在线阅读,更多相关《衡阳市八中day2修正版solution.docx(14页珍藏版)》请在冰豆网上搜索。

衡阳市八中day2修正版solution.docx

衡阳市八中day2修正版solution

第一题

记得Mario64上有一个游戏,古代背景,点击一个格子就会使得它周围3x3范围内的格子翻动,要求在3步之内把格子翻成上面的图案。

此题类似,只不过是翻动本身和上下左右范围内的5个格,为怎样翻动才能翻成全为0的状态。

要求输出翻动方式(1是翻动,0是不翻动)且按字典序排列最靠前的那个。

首先注意字典序:

记住,越靠上及越靠右的格子字典顺序越靠前。

故第一个1越靠下,靠左最好。

本题的搜索不太容易想到。

如果直接暴搜,O(2^(n^2))的时间复杂度会算到地老天荒——所以观察,可以发现,如果第一行的翻动方式确定了,就可以唯一确定第二行的翻动方式。

原因是翻动过的第一行内,如果是1的格子,下面第二行必须翻动,第一行如果为0,下面第二行必须不翻动。

否则第一行的非0值就再也没有什么东西可以救它了。

于是时间复杂度直降O(2^n),可以搜索了。

无需剪枝,125MS可以接受。

第二题:

Thestartingpointhereisadynamicprogrammingalgorithm.Arbitrarilyrootthetreeandconsider"cuttingoff"aparticularsubtreeinasoldering.Thisleavesone(ornoneifawirewascutoffatitsendpoints)"cutwire"whichextendsoutofthesubtreetotheparentandasetofwiresthatarewhollywithinthesubtree.Now,notethatallthatisrelevantisthelengthofthe"cutwire"withinthesubtreeandthetotalcostofalltheotherwires.Thisisbecausethecutwireistheonlywirewhosecostdependsontherestofthesoldering.

Thisgivesarelativelysimpledynamicprogrammingsolution:

foreachvertex(definingasubtree)store,foreachpossiblecutwirelength,theminimumcostoftheotherwires;ifthereisnocutwirethiscanbetakenasawireoflength0.Wewillcomputethesefromthebottomup.Tocomputethesevalues,notethatifthereisacutwireitmustextenddowntooneofthechildren;thecostforacutwiregoingthroughaparticularchildisthecostforthecutwirethroughthechild'ssubtreeplustheminimumcostsolderingcoveringeachoftheothersubtrees.Ifthereisnocutwire,thentheedgegoingtotheparentmustbesolderedontothemiddleofanotherwire;thenonecanjustcheckallpairsoflengthsanddistinctchildrentofindtwo"cutwires"fortwochildrentomergeintointoonewire.Now,notethatthemaximumlengthcutwireforeachsubtreeisthenumberofnodesitcontains,sothenumberofpairsoflengthsforanytwodistinctchildrenisatmostthenumberofpairsofnodesinthetwochildren;summingoverallchildrenthisisthenumberofnodeswhoselowestcommonancestoristherootofthesubtree.Thenthetotalworkdoneoverthewholealgorithmisonlythetotalnumberofpairsofnodes,orO(N2).

Now,atthispointitwillbeconvenienttoassume,inthediscussionofthealgorithm,thateachvertexhasatmosttwochildren.Infact,thisisnotaproblem:

avertexVwithmorechildrencanbe"splitup"bygivingitadirectedgetooneofitschildrenandattachingtheremaindertoanewvertexV'withanedgetoitfromVoflength0(thelengthdoesnotbreakthealgorithmalthoughalledgesintheproblemwereoflength1),theniteratingthisuntilnovertexhasmorethantwochildren.

Tofurtherreducetheruntime,onemustnotetheconvexitypropertiesofthesquaringofthelength.Ifonelooksatalength/costpair(l,c)forasubtree,itcorrespondstothefunction(L+l)2+cwhereListhelengthofthecutwireoutsidethesubtree.ButoneonlycaresaboutthosefunctionsthataretheminimumforsomevalueofL:

since(L+l)2 +c=L2 +2L*l+(l2+c),thisisthelowerenvelopeofthesefunctions,equivalenttoaconvexhull.Allpairsnotintheenvelopecanbedeleted.Onecanthenbinarysearchtheconvexhulltofindtheoptimalpairingwithanyparticularlengthofthewireoutsidethesubtree.Thentofindtheoptimalpairoflengthsinthetwochildrentomergeintoonewire,onecansimplytakeallthelengthsinthesmallersubtreeandbinarysearchtheconvexhullinthelargersubtreetofindthebestthingwithinthatsubtreetopairitwith.Finally,toefficientlyfindtheconvexhullsforallsubtrees,onecanrepresenttheconvexhullswithbinarysearchtrees(std:

:

setdoesfinehere)andtogetthepossibilitiesfromeitherchild,onecanoffsetthevaluesinthelargerchildsubtree'sconvexhull(bystoringoffsetvaluesthatareaddedtoallthepairsinthehull,sincebothlengthandcostchangeasyoumergesubtrees)andtheninserteachpair(offset)fromthesmallersubtreeintoit.Thetotalnumberofoperationsonthebinarysearchtreesisthenatmostthesumofthesizesofthesmallerchildsubtreefromeachnode(infactitcanbesmallerastheconvexhullcanhavefewerelementsthanthesizeofthesubtree).ThiscanbeshowntobeO(NlogN):

onecanconsiderthenumberoftimeseachpositiongetsmergedintoalargergroup,andnotethatitisalwayslessthanlogNsincewitheachmergeonlythevaluesinthesmallerhalfareincremented.EachtreeoperationisO(logN),sotheoverallruntimeisO(Nlog2 N).

BelowisNealWu'sN2 implementation:

#include

#include

#include

usingnamespacestd;

FILE*in=fopen("solder.in","r"),*out=fopen("solder.out","w");

constintMAXN=50005;

constlonglongLLINF=1LL<<60;

intN,down[MAXN];

longlong*dp[MAXN],mindp[MAXN];

vectoradj[MAXN];

voidinit_dfs(intnum,intpar)

{

down[num]=1;

intpar_ind=-1;

for(inti=0;i<(int)adj[num].size();i++)

{

intchild=adj[num][i];

if(child==par)

{

par_ind=i;

continue;

}

init_dfs(child,num);

down[num]=max(down[num],down[child]+1);

}

if(par_ind!

=-1)

adj[num].erase(adj[num].begin()+par_ind);

}

voidsolve_dfs(intnum)

{

for(inti=0;i<(int)adj[num].size();i++)

solve_dfs(adj[num][i]);

longlongdp1=1;

if(adj[num].size()>1)

{

for(inti=0;i<(int)adj[num].size();i++)

dp1+=mindp[adj[num][i]];

longlongbest_two=LLINF;

for(inti=0;i<(int)adj[num].size();i++)

for(intj=i+1;j<(int)adj[num].size();j++)

{

intchild1=adj[num][i],child2=adj[num][j];

for(inta=1;a<=down[child1];a++)

for(intb=1;b<=down[child2];b++)

best_two=min(best_two,dp[child1][a]+dp

[child2][b]+2LL*a*b-mindp[child1]-mindp[child2]);

}

dp1+=best_two;

}

dp[num]=newlonglong[down[num]+1];

dp[num][1]=dp1;

if(adj[num].size()==1)

{

dp[num][1]=LLINF;

dp[num][0]=mindp[adj[num][0]];

}

else

dp[num][0]=dp[num][1]-1;

for(intk=1;k

{

longlongsum=0,best_link=LLINF;

for(inti=0;i<(int)adj[num].size();i++)

{

intchild=adj[num][i];

sum+=mindp[child];

if(k<=down[child])

best_link=min(best_link,dp[child][k]-mindp[child]);

}

dp[num][k+1]=sum+best_link+2*k+1;

}

mindp[num]=LLINF;

for(intk=1;k<=down[num];k++)

mindp[num]=min(mindp[num],dp[num][k]);

for(inti=0;i<(int)adj[num].size();i++)

deletedp[adj[num][i]];

}

intmain()

{

fscanf(in,"%d",&N);

for(inti=1,a,b;i

{

fscanf(in,"%d%d",&a,&b);a--;b--;

adj[a].push_back(b);

adj[b].push_back(a);

}

init_dfs(0,-1);

solve_dfs(0);

fprintf(out,"%lld\n",dp[0][0]);

return0;

}

AndbelowisMichaelCohen'simpressivefullimplementation:

#include

#include

#include

#defineendl'\n'

usingnamespacestd;

structposs{

longlongdepth;

longlongcost;

longlongtakeover;

booltcheck;

};

booloperator<(possa,possb){

if(a.tcheck||b.tcheck)return(a.takeover

if(a.depth>b.depth)returntrue;

if(a.depth

return(a.cost

}

intN;

vectoredges[50000];

boolvisited[50000];

longlongdepth[50000];

longlongoffset[50000];

set*best[50000];

voidrecurse(intnode){

visited[node]=true;

longlongbestPair=-1;

longlongallSoFar=0;

for(inti=0;i

if(visited[edges[node][i]])continue;

depth[edges[node][i]]=depth[node]+1;

recurse(edges[node][i]);

longlongtadd;

{

posswhen={0,0,-depth[node],true};

set:

:

iteratorwhich=best[edges[node][i]]->upper_bound(when);

which--;

tadd=

(depth[node]-which->depth)*(depth[node]-which->depth)+which->cost+offset[edges[node][i]];

}

if(bestPair!

=-1)bestPair+=tadd;

if(best[node]==NULL){

best[node]=best[edges[node][i]];

offset[node]=offset[edges[node][i]];

}

else{

set*s=best[node],*t=best[edges[node][i]];

longlongos=offset[node]+tadd,ot=offset[edges[node][i]]+allSoFar;

if(s->size()size()){

set*tem=s;

s=t;

t=tem;

intto=os;

os=ot;

ot=to;

}

for(set:

:

iteratorit=t->begin();it!

=t->end();it++){

posswhen={0,0,it->depth-2*depth[node],true};

set:

:

iteratorwhich=s->upper_bound(when);

which--;

longlongthisPair=

(it->depth+which->depth-2*depth[node])*(it->depth+which->depth-2*depth[node])+it->cost+which->cost+offset[node]+offset[edges[node][i]];

if(bestPair==-1||thisPair

}

for(set:

:

iteratorit=t->begin();it!

=t->end();it++){

possp=*it;

p.cost+=ot-os;

set:

:

iteratorwhere=s->insert(p).first;

boolkilled=false;

while(where!

=s->begin()){

set:

:

iteratorprev=where;

prev--;

if(prev->depth==where->depth){

s->erase(where);

killed=true;

break;

}

p.takeover=

(where->cost-prev->cost+where->depth*where->depth-prev->depth*prev->depth)/(2*prev->depth-2*where->depth);

while((2*prev->depth-2*where->depth)*p.takeover<

where->cost-prev->cost+where->depth*where->depth-prev->depth*prev->depth)

p.takeover++;

s->erase(where);

where=s->insert(p).first;

if(where->takeover<=prev->takeover)s->erase(prev);

elsebreak;

}

if(killed)continue;

if(where==s->begin()){

p.takeover=-1000000000;

s->erase(where);

where=s->insert(p).first;

}

set:

:

iter

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 哲学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1