NYOJ 30 Gone Fishing(贪心)
Gone Fishing
時(shí)間限制:3000?ms ?|? 內(nèi)存限制: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個(gè)小時(shí)的釣魚時(shí)間,一共有n個(gè)湖泊,它們?cè)谝粭l直線上。從第1個(gè)湖開始,可以在任意一個(gè)湖停下,每到達(dá)一個(gè)湖,這個(gè)湖開始有f[i]條魚,釣一次魚需要5分鐘,5分鐘后這個(gè)湖的魚的數(shù)量為上次數(shù)量減去d[i],并且從第i個(gè)湖到第i+1個(gè)湖需要ti*5的時(shí)間。如果某個(gè)時(shí)間段期望釣到的魚數(shù)小于或者等于di,那么下一個(gè)時(shí)間段湖中將不再有魚剩下。為了簡(jiǎn)化計(jì)劃,John假設(shè)沒有其他釣魚人影響到他的釣魚數(shù)目。目標(biāo)是讓他能釣到的魚最多。在每個(gè)湖他所花的時(shí)間必須是5分鐘的倍數(shù)。
分析:為了敘述方便,把釣5分鐘魚稱為釣一次魚。首先枚舉John需要走過的湖泊數(shù)X,也就是假設(shè)他從湖泊1走到湖泊X,在湖泊X停止釣魚,則路上花去的時(shí)間記為time[X]。在這個(gè)前提下,可以認(rèn)為John能從一個(gè)湖“瞬間轉(zhuǎn)移”到另一個(gè)湖,那么在任意一個(gè)時(shí)刻都可以從湖泊1到湖泊X中任選一個(gè)湖泊來釣魚。因此,采取貪心策略,每次選一個(gè)魚最多的湖泊來釣魚。對(duì)于每個(gè)湖泊而言,由于在任何時(shí)候魚的數(shù)量之和John在該湖釣魚的次數(shù)有關(guān),而和釣魚的總次數(shù)無關(guān),所以這個(gè)策略是最優(yōu)的。假設(shè)一共允許釣k次魚,那么每次在n個(gè)湖泊中選擇魚最多的一個(gè)湖泊釣,選擇每次釣魚地點(diǎn)的時(shí)間復(fù)雜度為O(n),總的時(shí)間復(fù)雜度為O(kn^2)。如果用優(yōu)先隊(duì)列來做,總的時(shí)間復(fù)雜度可以降為O(knlogn)。
不用優(yōu)先隊(duì)列的方法:
#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]; //注意不要直接對(duì)f[i]進(jìn)行操作,不然會(huì)影響下一次的結(jié)果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; }
使用優(yōu)先隊(duì)列:
#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
總結(jié)
以上是生活随笔為你收集整理的NYOJ 30 Gone Fishing(贪心)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NYOJ 586 疯牛 POJ 245
- 下一篇: 谈谈双亲委派模型的第四次破坏-模块化