Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 8302 | Accepted: 3249 |
Description
- Any hotel which is closer to the seashore than M will be more expensive than M.
- Any hotel which is cheaper than M will be farther away from the seashore than M.
Input
Output
Sample Input
5 300 100 100 300 400 200 200 400 100 500 0
Sample Output
2
-------------------------------------------------
分析:这道题折腾了我一晚上也没AC,直到第二天早上起来才恍然大悟,心里暗骂出题人100遍,网上有人说貌似是楼教主出的,好吧我承认一开始我对题的理解有问题。首先,这道题的模型很简单,即任何比M旅店离海边近的旅店都比M酒店要贵,至于第二个条件,其实就是第一个条件的逆否命题,用来迷惑你的,嘿嘿!现在的关键是我们如何理解这个条件并把它转化为数学语言,你可能二话不说直接写出了这个数学形式的逻辑语句:∀i,if Di<DM ⇒ Ci>CM ,能写出来这个,证明你高一数学学的很好,跟我一样好。但是我们都犯了一个错误,那就是没有结合题意去讨论特殊情形。首先,我们看一下样例输入,发现有两个旅店距离海边都为100,它们同是离海边最近的旅店,但是它们的价格是不一样的,Smith夫妇选旅店会把它们两个同时作为候选项吗?显然不会!距离相同时,它们当然只会把更便宜的作为候选项,贵的那个直接抛弃!而对于我们之前写的表达式,显然它们两个是都满足的,原因是我们并没有考虑到距离相同时的情形,当然如果出题人好心的话也应该指出这种情况。修改后的逻辑语句:∀i,if Di≤DM ⇒ Ci>CM
接下来的思路就明朗了,我们依据离海边的距离对所有旅店进行排序,这里我们使用的是修改后的快速排序(即对D进行排序,C跟随,当然把旅店定义成结构体或类更方便),当两个酒店离海边距离相同时,我们把便宜的那个排在前面,然后我们就可以把D看成自变量x,C看成因变量y,初始时就已经有一个满足条件的旅店M(因为没有比排在最前面的那个旅店离海边更近并且还更便宜的了),即初始时candidate_n = 1,我们从第二个旅店向后扫描C,每找到一个CM比之前的C都小,计数器candidate_n就加1,最后输出candidate_n即可。
源码:
#include<iostream> using namespace std; void exchange(int A[], int i, int j) // 交换A[i]和A[j] { int temp = A[i]; A[i] = A[j]; A[j] = temp; } int partition(int A[], int B[], int left, int right)// 划分函数 { int pivot_A = A[right]; // 选择子数组最后一个元素作为基准 int pivot_B = B[right]; int tail = left - 1; // tail为小于基准的子数组最后一个元素的索引 for (int i = left; i < right; i++) // 遍历基准以外的其他元素 { if (A[i] < pivot_A) // 把小于基准的元素放到前一个子数组中 { tail++; exchange(A, tail, i); exchange(B, tail, i); } if (A[i] == pivot_A && B[i] < pivot_B) // 当两个酒店离海边距离相同时,我们把便宜的那个排在前面 { tail++; exchange(A, tail, i); exchange(B, tail, i); } } exchange(A, tail + 1, right); // 最后把基准放到前一个子数组的后边,剩下的子数组既是大于基准的子数组 exchange(B, tail + 1, right); return tail + 1; // 返回基准的索引 } void quicksort(int A[], int B[], int left, int right) { int pivot_index = A[right]; if (left < right) { pivot_index = partition(A, B, left, right); quicksort(A, B, left, pivot_index - 1); quicksort(A, B, pivot_index + 1, right); } } int main() { int N,candidate_n = 0; while (scanf("%d", &N) && N) // 输入酒店的个数N,N为0时直接结束程序 { int* D = (int *)malloc(N * sizeof(int));// 为了节省空间这里我们根据N的大小动态分配内存 int* C = (int *)malloc(N * sizeof(int)); for (int i = 0; i < N; i++) { scanf("%d%d", &D[i], &C[i]); } quicksort(D, C, 0, N - 1); // 调用修改后的快排算法依据D对旅店进行排序,C跟随 int min = C[0]; candidate_n = 1; // 排在最前面的旅店必然满足条件 for (int i = 1; i < N; i++) { if (C[i] < min) // 每找到一个旅店比前面的都便宜 { min = C[i]; candidate_n++; // 计数器加1 } } printf("%d ", candidate_n); candidate_n = 0; free(D); // 释放空间 free(C); } return 0; }
显然,程序的时间复杂度O(nlogn),运行结果如下: