[USACO] Barn Repair

    技术2022-05-19  18

    这道题自己一直找不到贪婪准则,于是看了前面的TEXT,得到了提示,终于写出来了。。。

    对于题目中的例子我们可以这么想,如果M=1,那么最少的stall数量为43-3+1=41,如果我们增加一根木板使M=2,这时该如何处理?

    其实这就相当于把一个木板找个位置砍掉一段,在哪个位置呢?

    连续的空的stall最长的两个端点,这样就使得得到的两个划分既覆盖了所有有牛的stall,有排除了最多的空的stall。

    这就是贪婪的准则,按照此准则求解一定是局部最优的,当M个木板用完时,得到的结果即为全局最优解。。。

    本题例子比较迷惑,我想当然的以为所有的输入是排好序的,结果贡献了一次WA。。。

    由于昨天刚被快排折磨过,今天写的异常顺利,看来练练还是有效果的:)

     


    /* ID: LANG: C TASK: barn1 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define SZ 200 void quicksort(int *p, int low, int high) { if(low >= high) return; int i = low, j = high, pivot = p[low]; while(i < j) { while(i < j && pivot < p[j]) j--; if(i < j) { p[i] = p[j]; i++; } while(i < j && p[i] < pivot) i++; if(i < j) { p[j] = p[i]; j--; } } p[i] = pivot; quicksort(p, low, i - 1); quicksort(p, i + 1, high); } int main() { FILE *fin = fopen("barn1.in", "r"); FILE *fout = fopen("barn1.out", "w"); int M, S, C; int i, j, k, last, total, stl_num; int stalls[SZ + 1] = {0}; int input[SZ] = {0}; fscanf(fin, "%d %d %d", &M, &S, &C); for(i = 0; i < C; i++) { fscanf(fin, "%d", &input[i]); } quicksort(input, 0, C - 1); total = S; stl_num = input[0]; total = total - stl_num + 1; last = stl_num; for(i = 1; i < C; i++) { stl_num = input[i]; stalls[stl_num] = stl_num - last - 1; last = stl_num; } total -= S - last; for(i = 0; i < M - 1; i++) { k = 0; for(j = 1; j <= S; j++) { if(stalls[j] > stalls[k]) { k = j; } } total -= stalls[k]; stalls[k] = 0; } fprintf(fout, "%d/n", total); exit(0); }


    分析的解法一想法跟我的差不多(怎么总是差不多?),不过它计算的是没有覆盖木板的空的stall的数量,然后用S减去这个值。。。

    分析的解法二只有代码,乱遭儿的看不懂,有大牛看懂了请在底下留个言,共同学习。。。


    这道题仔细一想还真就不难,可是怎么就找不到贪婪准则呢?面壁思过去!@_@

     

     


    最新回复(0)