NYOJ 30 Gone Fishing(贪心)
Gone Fishing
時間限制:3000?ms ?|? 內存限制:65535?KB 難度:5 描述Write a program to help John plan his fishing trip to maximize the number of fish expected to be caught. The number of minutes spent at each lake must be a multiple of 5.?
輸入
If multiple plans exist, choose the one that spends as long as possible at lake 1, even if no fish are expected to be caught in some intervals. If there is still a tie, choose the one that spends as long as possible at lake 2, and so on. Insert a blank line between cases.?
題意:John有h個小時的釣魚時間,一共有n個湖泊,它們在一條直線上。從第1個湖開始,可以在任意一個湖停下,每到達一個湖,這個湖開始有f[i]條魚,釣一次魚需要5分鐘,5分鐘后這個湖的魚的數量為上次數量減去d[i],并且從第i個湖到第i+1個湖需要ti*5的時間。如果某個時間段期望釣到的魚數小于或者等于di,那么下一個時間段湖中將不再有魚剩下。為了簡化計劃,John假設沒有其他釣魚人影響到他的釣魚數目。目標是讓他能釣到的魚最多。在每個湖他所花的時間必須是5分鐘的倍數。
分析:為了敘述方便,把釣5分鐘魚稱為釣一次魚。首先枚舉John需要走過的湖泊數X,也就是假設他從湖泊1走到湖泊X,在湖泊X停止釣魚,則路上花去的時間記為time[X]。在這個前提下,可以認為John能從一個湖“瞬間轉移”到另一個湖,那么在任意一個時刻都可以從湖泊1到湖泊X中任選一個湖泊來釣魚。因此,采取貪心策略,每次選一個魚最多的湖泊來釣魚。對于每個湖泊而言,由于在任何時候魚的數量之和John在該湖釣魚的次數有關,而和釣魚的總次數無關,所以這個策略是最優的。假設一共允許釣k次魚,那么每次在n個湖泊中選擇魚最多的一個湖泊釣,選擇每次釣魚地點的時間復雜度為O(n),總的時間復雜度為O(kn^2)。如果用優先隊列來做,總的時間復雜度可以降為O(knlogn)。
不用優先隊列的方法:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int N = 30; int f[N], d[N], ans[N], tmp[N], time[N]; int ff[N]; int main() {int n, h, i, j, t, cas = 0;while(~scanf("%d",&n) && n){scanf("%d",&h); h *= 60;for(i = 0; i < n; i++)scanf("%d",&f[i]);for(i = 0; i < n; i++)scanf("%d",&d[i]);time[0] = 0;for(i = 1; i < n; i++){scanf("%d",&t);time[i] = time[i-1] + t*5;}memset(ans, 0, sizeof(ans)); //注意初始化int maxsum = -1;for(i = 0; i < n; i++){int sum = 0, left_time = h - time[i];for(j = 0; j <= i; j++)ff[j] = f[j]; //注意不要直接對f[i]進行操作,不然會影響下一次的結果memset(tmp, 0, sizeof(tmp));while(left_time > 0){int mmax = 0, id = 0;for(j = 0; j <= i; j++){if(ff[j] > mmax){mmax = ff[j];id = j;}}if(mmax == 0) break;sum += mmax;tmp[id] += 5;ff[id] -= d[id];left_time -= 5;}if(left_time > 0)tmp[0] += left_time;if(sum > maxsum){maxsum = sum;for(j = 0; j <= i; j++)ans[j] = tmp[j];}}if(cas > 0)printf("\n");printf("%d",ans[0]);for(i = 1; i < n; i++)printf(", %d",ans[i]);printf("\n");printf("Number of fish expected: %d\n",maxsum);cas++;}return 0; }
使用優先隊列:
#include<stdio.h> #include<string.h> #include<queue> #include<algorithm> using namespace std;struct node {int id;int fish;int down;int time;friend bool operator < (const node &x, const node &y){if(x.fish != y.fish)return x.fish < y.fish;return x.id > y.id;} }a[30]; priority_queue<node> q; int h, n, ans[30], tmp[30], maxsum;void greedy() {int i, j;maxsum = -1;for(i = 0; i < n; i++){while(!q.empty()) q.pop();for(j = 0; j <= i; j++)q.push(a[j]);int left_time = h - a[i].time, sum = 0;memset(tmp, 0, sizeof(tmp));while(left_time > 0){node temp = q.top();q.pop();if(temp.fish <= 0) break;sum += temp.fish;temp.fish -= temp.down;tmp[temp.id] += 5;q.push(temp);left_time -= 5;}if(left_time > 0)tmp[0] += left_time;if(sum > maxsum){maxsum = sum;for(j = 0; j < n; j++)ans[j] = tmp[j];}} }int main() {int i, t, cas = 0;while(~scanf("%d",&n) && n){scanf("%d",&h);h *= 60;for(i = 0; i < n; i++){scanf("%d",&a[i].fish);a[i].id = i;}for(i = 0; i < n; i++)scanf("%d",&a[i].down);a[0].time = 0;for(i = 1; i < n; i++){scanf("%d",&t);a[i].time = a[i-1].time + t * 5;}if(cas > 0)printf("\n");cas++;greedy();printf("%d",ans[0]);for(i = 1; i < n; i++)printf(", %d",ans[i]);printf("\n");printf("Number of fish expected: %d\n",maxsum);}return 0; }
參考資料:http://blog.csdn.net/shuangde800/article/details/7828547
總結
以上是生活随笔為你收集整理的NYOJ 30 Gone Fishing(贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NYOJ 586 疯牛 POJ 245
- 下一篇: 谈谈双亲委派模型的第四次破坏-模块化