专题:寒假第二阶段考试组题 Group Problems in the Second Stage of Winter Holiday
写在前面
春到福来,春风万家又一载!
正值农历新年之际,给各位观众姥爷拜年了!
好了不贫了,回到正题:寒假考试的题量比较大,每天的时间安排也很紧,所以Peter并不会有太多的分析。(主要是寒假作业没写完)为了防止篇幅过小就以组题的形式开博客吧!
惯例,组题(一)传送门:
T2不会写,仙姑为敬
寒假的题真的对像我这样的蒟蒻很不友好QAQ
啊对了,还有句话给自己洗一下:小蒟蒻实在是不会用TinyMCE以及Markdown,公式将就着看好吧O(∩_∩)O谢谢
1.CF448C Painting Fence
由题意可知,给出n个整数ai,每次只能消除一列或一行.
这题的错误思路主要是dp、贪心和搜索.(窝才不会告诉泥萌窝对着这几个做法怼了俩小时@障智常正非)
易证,若有一列是竖着涂的,则该列下方所有行都是横着涂的.(非常重要的性质!!!)
首先搞个分治框架,solve(l,r,step),表示从第l列到第r列这个区间已经消除step次的最少消除步数.
然后,由于之前的性质我们可以对这一行扫一遍,找出所有列中最小的高度,将所有列共同删去这一高度.(如下图是一个简单的栗子)
接着,再对该行扫一遍,对上方的小块继续分治下去(分割子局面),最终全部消除.
细节:这样的小块消除方法不一定是最优的,还应该与直接一列列消除的方式比较取最小值.
搞定!
T1到此结束,代码见文末代码块1.
时间有限,T2~T4仙姑为敬!
Na么,组题(一)就讲完了,感觉如何?(这谁挡得住啊)
好啦,下次见!
完结撒花!
真没了,回去吧
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read() 4 { 5 int ret=0,f=1; 6 char ch=getchar(); 7 while(ch>'9'||ch<'0') 8 { 9 if(ch=='-') 10 f=-1; 11 ch=getchar(); 12 } 13 while(ch>='0'&&ch<='9') 14 { 15 ret=(ret<<1)+(ret<<3)+ch-'0'; 16 ch=getchar(); 17 } 18 return ret*f; 19 } 20 int n,h[5010]; 21 int solve(int l,int r,int lh) 22 { 23 if(l>r) 24 return 0; 25 int res=0,minh=1000000007,la=l-1; 26 for(register int i=l;i<=r;i++) 27 minh=min(minh,h[i]);//找出最小高度,一次性涂掉 28 res=minh-lh; 29 for(register int i=l;i<=r;i++) 30 if(h[i]==minh) 31 res+=solve(la+1,i-1,minh),la=i;//O(n)扫一遍(分割子局面) 32 res+=solve(la+1,r,minh);//剩下的一个子局面 33 return min(res,r-l+1);//一列一列涂色和一次性横着涂的更优解 34 } 35 void work() 36 { 37 n=read(); 38 for(register int i=1;i<=n;i++) 39 h[i]=read(); 40 printf("%d\n",solve(1,n,0)); 41 } 42 int main() 43 { 44 //freopen("color.in","r",stdin); 45 //freopen("color.out","w",stdout); 46 work(); 47 return 0; 48 }
(放代码处)