poj 2008 Moo University - Team Tryouts 解题报告2
上一篇根据其他博主的算法,对该题进行了详细的剖析,但原来自己的算法一直都超时,经过修改,终于Time: 938MS 过了,泪奔,代码如下:
//具体思路:对h进行递增排序,固定h,再对每个w进行扫描,即可扫描得到结果,但超时,需要进行改进
//根据 A * H + B * W <= A * h + B * w + C,其中 A * H + B * W是不可能改变的,故对其进行递增排序,
//在比较期间,因为h是不变的,w是递增的,所以A * h + B * w + C是递增的,可以根据上一断点进行比较,剪掉了没有意义的比较
//但每次w比较完毕,在进行下一次w比较时,需要减去原来w的数量,因为w是递增的,而小于w是无法参加比赛的
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_N 1024 typedef struct _calf { int w, h, k; }calf; int n, a, b, c, ans, cnt; calf gcalf[MAX_N], calf_h[MAX_N], calf_w[MAX_N]; int cmp_w(const void *a, const void *b) { return (((calf *)a)->w - ((calf *)b)->w); } int cmp_h(const void *a, const void *b) { return ((calf *)a)->h - ((calf *)b)->h; } int cmp_k(const void *a, const void *b) { return ((calf *)a)->k - ((calf *)b)->k; } void input() { int i; for (i = 0; i < n; ++i) { scanf("%d %d", &gcalf[i].h, &gcalf[i].w); gcalf[i].k = a * gcalf[i].h + b * gcalf[i].w; } memcpy(calf_h, gcalf, n * sizeof(calf)); } int main() { scanf("%d %d %d %d", &n, &a, &b, &c); input(); qsort(gcalf, n, sizeof(calf), cmp_k); qsort(calf_h, n, sizeof(calf), cmp_h); memcpy(calf_w, calf_h, n * sizeof(calf)); ans = 0; int i, j, k, m, t, w(0), h(0); for (i = 0; i < n; ++i) { if(h == calf_h[i].h) continue; h = calf_h[i].h;
//h固定,进行w排序 qsort(calf_w + i, n - i, sizeof(calf), cmp_w); w = 0; k = 0; cnt = 0; for (j = i; j < n; ++j) { if(w == calf_w[j].w) continue; if(n - j < ans) break; w = calf_w[j].w; t = a * h + b * w + c;
//获取符合条件的小牛 for (; k < n; ++k) { if(gcalf[k].k > t) break; else if(gcalf[k].h >= h && gcalf[k].w >= w) ++cnt; } if(ans < cnt) ans = cnt;
//减去 w 的小牛,因为下一次增加了w之后,本次w的小牛必须剔除 for(m = 0; m < k; ++m) { if(gcalf[m].w == w && gcalf[m].h >= h && gcalf[m].k <= t) --cnt; } } memcpy(calf_w + i, calf_h + i, (n - i) * sizeof(calf)); } printf("%d\n", ans); return 0; }
整个算法刚刚卡在1000ms内,有点运气,感觉是每次的快排造成的原因,故想了办法去掉了排序,提高了200ms,也算是有所得吧, 下一次是 Time: 766MS
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_N 1024 typedef struct _calf { int w, h, k; }calf; int n, a, b, c, ans, cnt; calf gcalf[MAX_N], calf_h[MAX_N], calf_w[MAX_N]; int cmp_w(const void *a, const void *b) { return (((calf *)a)->w - ((calf *)b)->w); } int cmp_h(const void *a, const void *b) { return ((calf *)a)->h - ((calf *)b)->h; } int cmp_k(const void *a, const void *b) { return ((calf *)a)->k - ((calf *)b)->k; } void input() { int i; for (i = 0; i < n; ++i) { scanf("%d %d", &gcalf[i].h, &gcalf[i].w); gcalf[i].k = a * gcalf[i].h + b * gcalf[i].w; } memcpy(calf_h, gcalf, n * sizeof(calf)); } int main() { scanf("%d %d %d %d", &n, &a, &b, &c); input(); qsort(gcalf, n, sizeof(calf), cmp_k); qsort(calf_h, n, sizeof(calf), cmp_h); memcpy(calf_w, calf_h, n * sizeof(calf));
//对整个w进行一次排序 qsort(calf_w, n, sizeof(calf), cmp_w); ans = 0; int i, j, k, m, t, w(0), h(0); for (i = 0; i < n; ++i) { if(h == calf_h[i].h) continue; h = calf_h[i].h;
//不需要每次都排序了 // qsort(calf_w + i, n - i, sizeof(calf), cmp_w); w = 0; k = 0; cnt = 0; //每次都从0开始 for (j = 0; j < n; ++j) {
//在此对 <= w 或者 < h 的小牛进行剪枝,否则比刚才还费时 if(w >= calf_w[j].w || h > calf_w[j].h) continue; if(n - j < ans) break; w = calf_w[j].w; t = a * h + b * w + c; for (; k < n; ++k) { if(gcalf[k].k > t) break; else if(gcalf[k].h >= h && gcalf[k].w >= w) ++cnt; } if(ans < cnt) ans = cnt; for(m = 0; m < k; ++m) { if(gcalf[m].w == w && gcalf[m].h >= h && gcalf[m].k <= t) --cnt; } } // memcpy(calf_w + i, calf_h + i, (n - i) * sizeof(calf)); } printf("%d\n", ans); return 0; }
感觉如果还要快的话,可以对 m 循环那个做个精简,应该是用空间换取时间的做法,将每次为w的东东存储起来,那样应该能快很多,今天就写到这里, 欢迎拍砖