1. 程式人生 > >poj1042 Gone Fishing(貪心)

poj1042 Gone Fishing(貪心)

思路來源

題意

有h小時可以釣魚,每次釣魚5分鐘,

有n個釣魚場所,從i到i+1場所需要5*t[i]分鐘,

地點i,第一次釣魚可以得到f[i]條魚,

之後,每一次釣都會少d[i]條,

特別地,當f[i]-k*d[i]<=0時就釣不上來魚了。

問最多能釣多少條魚,輸出在每個區間釣魚的時間。

相同魚數時,儘可能讓最前面的時間多。

題解

列舉釣魚的終止區間i,即在[0,i]這段區間釣魚。

這裡,我們將時間均換算為5分鐘的倍數,h即為12*h個5min。

即刨去路上的時間,

剩下的時間12*h-\sum t[j],0<=j<i可以專心釣魚,

把這段區間的初始魚都放進優先佇列裡,

優先佇列裡先釣大的,每釣一條魚i,

就把它的當前權值減一次d[i]再放回去。

特別地,當權值為負時,就沒法釣了。

同魚數要求時,優先佇列內部排序按pos小的先釣。

所有魚都釣完還有時間剩餘的話,全待在0號漁場。

心得

貪心題,真的好迷啊,

自己寫的一個程式碼和答案高度相似,

也能過所有樣例,

但只要不按AC程式碼那麼改就是WA的...

程式碼①(WA程式碼)

#include <iostream>
#include <algorithm> 
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <bitset> 
const int INF=0x3f3f3f3f;
const int maxn=1e5+5;
const int mod=1e9+7;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int> 
#define si set<int>
#define pii pair<int,int> 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
ll n,ans,h,f[30],d[30],t[30],used[30],use[30]; 
struct node
{
	ll v,pos;
	node(ll vv,ll p):v(vv),pos(p){
	};
};
bool operator<(node a,node b)
{
	if(a.v==b.v)return a.pos>b.pos;
	return a.v<b.v;
}
priority_queue<node>q;
void init()
{
	while(!q.empty())q.pop();
	mem(f,0);
	mem(d,0);
	mem(t,0);
	mem(use,0); 
	mem(used,0);
	ans=-1;
}
int main()
{
	while(~scanf("%lld",&n)&&n)
	{
		init();
		scll(h);h*=12;//5分鐘的個數
		rep(i,0,n-1)scll(f[i]);
		rep(i,0,n-1)scll(d[i]);
		rep(i,0,n-2)scll(t[i]);
		rep(i,0,n-1)//列舉在[0,i]區間釣魚 
		{
			mem(use,0);
			ll T=h,tmpans=0;
			rep(j,0,i-1)T-=t[j];//餘下的T是釣魚時間 
			if(T<=0)break;//後面的沒法取了 
			while(!q.empty())q.pop();
			rep(j,0,i)q.push(node(f[j],j));
			while(!q.empty()&&T) 
			{
				node t=q.top(); 
				ll v=t.v,pos=t.pos;
				q.pop();
				tmpans+=v;use[pos]++;T--;
				if(v-d[pos]>0)q.push(node(v-d[pos],pos));
			}
			if(T)use[0]+=T;//剩下時間都呆在第一個點 
			if(tmpans>ans)//更新ans答案 
			{
				ans=tmpans;
				rep(j,0,n-1)used[j]=use[j];
			}
			else if(tmpans==ans)//更新讓前面的待時間更長答案 
			{
				bool flag=0;
				rep(j,0,n-1)
				{
					if(use[j]>used[j])
					{
					 flag=1;
					 break;
				    }
					else if(use[j]<used[j])break;
				}
				if(flag)
				{
				 rep(j,0,n-1)
				 used[j]=use[j];
			    }
			}
		}
		printf("%lld",5*used[0]);
		rep(j,1,n-1)printf(", %lld",5*used[j]);
		printf("\nNumber of fish expected: %lld\n\n",ans);
	}
   return 0;	
}

程式碼②(AC程式碼)

#include <iostream>
#include <algorithm> 
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <bitset> 
const int INF=0x3f3f3f3f;
const int maxn=1e5+5;
const int mod=1e9+7;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int> 
#define si set<int>
#define pii pair<int,int> 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
ll n,ans,h,f[30],d[30],t[30],used[30],use[30]; 
struct node
{
	ll v,pos;
	node(ll vv,ll p):v(vv),pos(p){
	};
};
bool operator<(node a,node b)
{
	if(a.v==b.v)return a.pos>b.pos;
	return a.v<b.v;
}
priority_queue<node>q;
void init()
{
	while(!q.empty())q.pop();
	mem(f,0);
	mem(d,0);
	mem(t,0); 
	mem(used,0);
	ans=-1;
}
int main()
{
	while(~scanf("%lld",&n)&&n)
	{
		init();
		scll(h);h*=12;//5分鐘的個數
		rep(i,0,n-1)scll(f[i]);
		rep(i,0,n-1)scll(d[i]);
		rep(i,0,n-2)scll(t[i]);
		rep(i,0,n-1)//列舉在[0,i]區間釣魚 
		{
			mem(use,0);
			ll T=h,tmpans=0;
			rep(j,0,i-1)T-=t[j];//餘下的T是釣魚時間 
			if(T<=0)break;//後面的沒法取了 
			while(!q.empty())q.pop();
			rep(j,0,i)q.push(node(f[j],j));
			while(T>0) 
			{
				node t=q.top(); 
				q.pop();
				//printf("T:%d\n",T);
				ll v=t.v,pos=t.pos;
				if(v<=0)break;
				tmpans+=v;use[pos]++;T--;
				q.push(node(v-d[pos],pos));
			}
			if(T>0)use[0]+=T;//剩下時間都呆在第一個點 
			if(tmpans>ans)//更新ans答案 
			{
				ans=tmpans;
				rep(j,0,n-1)used[j]=use[j];
			}
			else if(tmpans==ans)//更新讓前面的待時間更長答案 
			{
				bool flag=0;
				rep(j,0,n-1)
				{
					if(use[j]>used[j])
					{
					 flag=1;
					 break;
				    }
					else if(use[j]<used[j])break;
				}
				if(flag)
				{
				 rep(j,0,n-1)
				 used[j]=use[j];
			    }
			}
		}
		printf("%lld",5*used[0]);
		rep(j,1,n-1)printf(", %lld",5*used[j]);
		printf("\nNumber of fish expected: %lld\n\n",ans);
	}
   return 0;	
}