2017.3.3 双栈排序 失败总结
来源:互联网 发布:女生学金融 知乎 编辑:程序博客网 时间:2024/06/11 17:02
这道题虽然是noip的题,但还是很能反映你思维水平的、
说出来二分图、黑白染色对于一个oier来说肯定不陌生,有的人很快就能说出做法,写出程序。
但是一出成题怎么就不会了呢?
其实主要失误在于 我是站在选A、B的角度思考问题的,但实际上,如果思路足够清晰,还是能回到互斥的角度的
因为如果站在选A选B的角度上,能影响当前决策的实际上有3个不同的因素,1是出现顺序,这好办,扫过去就行。2是当前栈中元素的影响(这实际上是有后效性的,因为后面的数也会对当前决策造成影响:后面小数卡大数,导致空间被浪费,同时贪心是错的:不信用7251463 试试、),3是当前数消不消除的影响。。(这比较坑,但如果从第2点已经看出后效性的话已经证实至少不是1个dp解决问题的题了)
这时候应该敏锐地发现,这种后效性是由空间消耗造成的,因为我们的贪心实际上维护的是一个尽量装A的序列,如果是跳着从大到小的序列,那对A的空间利用极低。
(ps:最讨厌分析中的“不妨”,这俩字没有任何意义,,解题的每一步都应该在题目中有根据的,用“不妨”蒙混过关对自己的思维并没有太大的帮助)
当然,对于能处理的情况,我们首选A列,那么我们应该还是用dp来维护,但并不完成划分A、B工作,只是把能放在一个栈里的区间求出来,
然后由于非A即B,就需要利用黑白染色的互斥原理,进行遍历。
总结:这题分析不出来,主要是思路受尽量选A的条件制约,抓住贪心放不开,认为前几个都应该放A里,且忽略了可行性这一重要因素,可行性是受尽量选A影响的。
应建立在可行性上尽量选A,而不是在尽量选A中实现可行性。
补一下,个人感觉第一步的dp也挺难的、
可以从小的数据入手:
1 2 3 :肯定可以单栈; 1 3 2 :肯定可以单栈 2 1 3 肯定可以单栈 2 3 1:肯定不可以单栈(需要分开,且一定是2和3分开)
3 1 2 :肯定可以单栈 3 2 1 肯定可以单栈
这样就考虑了退出的情况,强行装,为什么不会出现不可行的情况?因为不可装只和弹出、装入有关,现在dp考虑了出栈,如果在加上弹出的情况,A装不下了,那就是无论如何也装不下了,只能另寻栈。
#include<iostream>#include<cstdio>using namespace std;int n,woc,a[99999],i,j,l,stacka[99998],stackb[99999],topa,topb,tu[1999][1999],sta[1999],ru[1999];bool keyi,zou[1999];void dfs(int now){if(keyi==0)return ;for(int i=1;i<=n;i++){ if(zou[i])continue;if(tu[i][now]||tu[now][i]){if((sta[now]==1&&sta[i]==1)||(sta[now]==2&&sta[i]==2)){keyi=0; return ;}if(sta[now]==1&&sta[i]==-1)sta[i]=2;if(sta[now]==2&&sta[i]==-1)sta[i]=1;zou[i]=1;dfs(i);}}}int main(){scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d",&a[i]);for(i=1;i<=n;i++)for(j=i+1;j<=n;j++){if(a[i]>a[j])continue;for(l=j+1;l<=n;l++){if(a[l]<a[i]&&a[l]<a[j]){tu[j][i]=1;ru[i]++;ru[j]++;}}}for(i=1;i<=n;i++)if(ru[i]>0)sta[i]=-1;else sta[i]=1;keyi=1;for(i=1;i<=n;i++){if(ru[i]==1&&sta[i]==-1){sta[i]=1;zou[i]=1;dfs(i); }}for(i=1;i<=n;i++)if(sta[i]==-1)keyi=0;if(!keyi){cout<<0;return 0;}stacka[0]=99999;stackb[0]=99999;woc=1;for(i=1;i<=n;i++){if(sta[i]==1){while(stacka[topa]<a[i]){if(stacka[topa]==woc){topa--;printf("b ");}else{ topb--;printf("d ");}woc++;}printf("a "); stacka[++topa]=a[i];}else {while(stacka[topa]==woc){topa--;printf("b ");woc++;}while(stackb[topb]<a[i]){if(stacka[topa]==woc){ topa--;printf("b ");}else{ topb--;printf("d ");}woc++;} stackb[++topb]=a[i];printf("c "); } }for(i=woc;i<=n;i++){if(stacka[topa]==i){printf("b ");--topa;}else {printf("d ");--topb;}}}
- 2017.3.3 双栈排序 失败总结
- 2017.3.6 种树 失败总结
- 2017.3.17 祭祀 失败总结
- 2017.3.7 搞笑世界杯 失败总结
- 2017.3.8 太空飞行计划问题 失败总结
- 2017.3.12 分割矩阵 失败总结
- 2017.3.13 反素数ant 失败总结
- 2017.3.14-9.1 玩具取名 失败总结
- 2017.3.14 游戏(scoi2009) 失败总结
- 2017.3.15 余数之和sum 失败总结
- 2017.3.19 约数个数和 失败总结
- 2017.3.31 棋盘制作 失败总结
- 20153743--3排序总结
- 排序算法总结3-插入排序
- 排序算法总结(3)--冒泡排序
- WEB失败项目总结
- 项目团队失败总结
- Mysql连接失败总结
- Android Studio更新出现错误:Error:Failed to open zip file解决方法
- argparse库的使用
- jQuery
- Java笔记2
- MongoDB【第二篇】集群搭建
- 2017.3.3 双栈排序 失败总结
- ScriptX控件如何在不跳转页面的情况下将要打印的内容打印出来
- 线索二叉树C/C++
- gcc/g++ 动态编译和链接问题
- mysql 特殊函数
- iOS10 不能跳转系统设置解决办法(1)
- gcc/g++编译参数详解
- 常见排序算法
- list转换datatable