题目链接
经典的DP问题。也可以用贪心的思想来做。
下面是我一开始的思路:(可以做,但是很麻烦)
这道题目一开始,我是用很浅薄的DP思想来做的。即设置一个结构体分别存储起始位置BEGIN和终止位置END。并且BEGIN<END.然后我写下了一些判断条件(也就是这些判断条件判断的不够细致,导致一些情况还是错了)最后一直陷于WA。后来才后知后觉,应该考虑奇数与偶数的情况。但是这样写下来太复杂了。
下面是之前的代码:(错误,仅供个人悔悟)
#include <iostream> using namespace std; struct room{ int begin; //开始房间 int end; //终止房间 bool res; //是否已经处理 }a[205]; int judge(struct room a[],int n){ int sum = 0; for (int i = 0; i < n; i++){ if (a[i].res == true) continue; a[i].res = true; sum += 10; for (int j = i + 1; j <= n; j++){ if ((a[j].begin > a[i].end) || (a[j].end < a[i].begin)){ /*if ((abs(a[i].end - a[j].begin )== 1) || (abs(a[i].begin - a[j].end) == 1)) continue; 需要考虑 1 3 4 5情况*/ a[j].res = true; } } } return sum; } void setNumber(struct room a[], int n){ for (int i = 0; i < n; i++){ if (a[i].end < a[i].begin){ int temp = a[i].begin; a[i].begin = a[i].end; a[i].end = temp; } a[i].res = false; } } int main() { int T, n; cin >> T; while (T--){ cin >> n; for (int i = 0; i < n; i++) cin >> a[i].begin >> a[i].end; setNumber(a, n); int sum = judge(a, n); cout << sum << endl; } return 0; }
在做这道题目时我学习了一种新的思想:统计思想。
即我们用一个数组来统计道路段被用到的次数。一个同样的道路段被用到了N次,所有的道路段我们都求出这个Ni。那么最后求出MAX(Ni)就是我们所要知道的最大冲突次数。
#include <iostream> using namespace std; int main() { int T, n, s, e, temp,max; cin >> T; while (T--) { int id[205] = { 0 }; max = 0; cin >> n; while (n--){ cin >> s >> e; if (s > e) //必须让开始的房号为小 { temp = s; s = e; e = temp; } for (int i = (s + 1) / 2; i <= (e + 1) / 2; i++) //无论是奇数还是偶数都+1然后除2 缩小范围 id[i]++; } for (int i = 0; i < 205; i++)//遍历寻找冲突次数最多的 if (max < id[i]) max = id[i]; cout << max * 10 << endl; } return 0; }
总结:这道题目,充分的说明了解题思维的重要性。错误的解题思维,只会引导出麻烦的做法,甚至是错误的做法。而正确的思维,则反之。