题目链接
唉,又是一道水题。
……每次花了一晚上\下午辛辛苦苦做完一题,总是看到一大堆的大神如此感叹到。由此更可以看出人与人之间的距离了。虽然很不愉快,很心酸看到这样的感叹,看到自己的千山万水竟是别人的谬之毫米。
……好想把心情写下去。不过怎么说,这是一篇讲题目的博客。如果有心情,再重新去写一篇吧!回归整体讲讲个人这题的经验。
题目要求输入长度l,重量w。并且求最短时间(详细题意,应该不用讲了吧?我英语很差的都看懂了说)
很显然这题要排序,而且是多元素排序,即可以先排序l,然后如果l是相等的元素,那么再根据w排序。比如说输入4 9 5 2 2 1 3 5 1 4排序完就是输出1 4 2 1 3 5 4 9 5 2了。
应为题目的意思是说,如果后面的比前面的大那么就不用时间了,所以,这里有一个陷阱,也是我毫不犹豫的踩进去的。即认为s[i+1].l<s[i].l || s[i+1].w<s[i].w就是必须给时间加1的(因为后面的元素存在比前面的小了),一开始这样想过去确实挺有道理的。可是看完答案就傻眼了吧。比如第一组输入数据你这样的话答案应该是3,而正确答案是2.
显然,这是思维的误区。至于哪里错呢?漏洞很多。
所以,我们应该排序没错。但是排序完要怎么做要参照题目的要求。具体的实现,请看如下代码中注释。
#include <iostream> #include <algorithm> using namespace std; struct stick{ int l; //长度 int w;//重量 bool flag; //判断是否访问过 }; bool cmp(const stick &s1, const stick &s2){ //升序排列 if (s1.l != s2.l)//第一排列元素 return (s1.l <= s2.l); else return (s1.w <= s2.w);//第二排列 } int main() { int T, n, res, i, j; stick s[5005], pre; cin >> T; while (T--){ cin >> n; for (i = 0; i < n; i++){ cin >> s[i].l >> s[i].w; s[i].flag = true; } sort(s, s + n, cmp); res = 0; for (i = 0; i < n; i++) { if (s[i].flag) //说明该结点还没有访问过(即W小于其前面一个) { s[i].flag = false; pre = s[i]; //设置从当前值往后寻找 for (j = i + 1; j < n; j++){ if (s[j].w >= pre.w&&s[j].flag == true) //如果后面的大于前面一个说明满足条件时间不必加1 { s[j].flag = false; //该结点满足设置为false后面就不用再访问这个结点了 pre = s[j]; } } res++; } } cout << res << endl; } return 0; }
总结:如果,你是和我一样的菜鸟。请记得,比你更牛逼的人,都已经把这题做完了,尽管他们略带轻蔑,可是他们还是那么一丝不苟的做完。所以,你凭什么逃避?