衡阳市八中day2修正版solution.docx
- 文档编号:10543481
- 上传时间:2023-02-21
- 格式:DOCX
- 页数:14
- 大小:73.65KB
衡阳市八中day2修正版solution.docx
《衡阳市八中day2修正版solution.docx》由会员分享,可在线阅读,更多相关《衡阳市八中day2修正版solution.docx(14页珍藏版)》请在冰豆网上搜索。
衡阳市八中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];
vector
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; vector boolvisited[50000]; longlongdepth[50000]; longlongoffset[50000]; set 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 longlongos=offset[node]+tadd,ot=offset[edges[node][i]]+allSoFar; if(s->size() set 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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 衡阳市 day2 修正 solution