POJ 1042 Gone Fishing
题意简述:
给定鱼塘个数、钓鱼时间,以及每个鱼塘内单位时间内能钓到的鱼的数量和时间的关系,以及从一个池塘到另一个池塘的花费时间。请给出一个最优策略,使得能钓到最多的鱼,且尽量在靠前的鱼塘花费更多的时间。(更多细节请看原题面)
解题思路:
本题采用贪心策略。如果我们在前k个池塘钓鱼,那么由于路上花费时间确定,那么就相当于剩下的时间我们就可以自由分配在前k个池塘上。于是就相当于没有了“单向前进”这一限制,我们每次就可以“自由的”选择当前能掉出的鱼数量最大的池塘。
于是我们枚举终点,即只在前1个池塘钓鱼、只在前2个池塘钓鱼、…、只在前n个池塘钓鱼,找出这些不同的阶段中钓鱼数量最大的那一个,并输出答案。
注意:如果所有池塘的鱼都被钓完,那么应当将所有剩下的时间都花费在第一个池塘。还需注意若钓鱼数相同,需要在靠前的池塘花费更多时间。记得初始化
代码示例:
#include<cstdio>
#include<algorithm>
#include<cstring>
int n,h;
int f[30],d[30],t[30],f2[30];
int ans[30],Stay[30],Stay2[30];
int getRes(int h2,int ed){
int mx = 0,pos,res = 0;
memset(Stay,0,sizeof Stay);
for(int i = 1;i <= ed;i++) f2[i] = f[i];
while(h2 >= 5){
mx = 0;
for(int i = 1;i <= ed;i++){
if(mx < f2[i]){
mx = f2[i]; pos = i;
}
}
// printf("%d %d %d %d %d\n",pos,f2[pos],res,h2,mx);
if(mx == 0) break;
h2 -= 5; res += f2[pos];
f2[pos] -= d[pos]; Stay[pos] += 5;
}
if(h2 > 0) Stay[1] += h2;
// printf("%d %d\n\n",h2,res);
return res;
}
void solve(){
int h2 = h,ans = 0;
memset(Stay2,0,sizeof Stay2);
for(int i = 1;i <= n;i++){
int tmp = getRes(h2,i);
if(ans <= tmp){
bool flag = true;
if(ans == tmp) for(int j = 1;j <= n;j++) if(Stay2[j] > Stay[j]) flag = false;
ans = tmp;
if(flag) for(int j = 1;j <= n;j++) Stay2[j] = Stay[j];
}
h2 -= 5*t[i];
}
for(int i = 1;i < n;i++) printf("%d, ",Stay2[i]);
printf("%d\n",Stay2[n]);
printf("Number of fish expected: %d\n\n",ans);
}
int main(){
while(true){
scanf("%d",&n);
if(n == 0) break;
scanf("%d",&h);h*= 60;
for(int i = 1;i <= n;i++) scanf("%d",f+i);
for(int i = 1;i <= n;i++) scanf("%d",d+i);
for(int i = 1;i < n;i++) scanf("%d",t+i);
solve();
}
return 0;
}
POJ 3069 Saruman’s Army
题意简述:
给定x轴上的若干点,这些点可能重叠,然后给定若干“雷达”,雷达的覆盖半径为R,要求花费最少的雷达覆盖所有的点(雷达只能放在所给的坐标上)。
解题思路:
将所有需要覆盖的坐标升序排列,对于最靠前的一个点,从该点出发向后找最后一个距离该点小于R的点,并将雷达放在其上。并将雷达范围内所有点标记,重复这一操作直到所有点都被覆盖。
代码示例:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
const int N = 1100;
int x[N],vis[N];
int r,n;
void solve(){
int ans = 0;
std::sort(x+1,x+n+1);
for(int i = 1;i <= n;i++){
if(vis[x[i]]) continue;
int pos = i;
for(int j = i+1;j <= n;j++){
if(x[j]-x[i] <= r) pos = j;
else break;
}
for(int j = i;j <= n;j++) if(abs(x[j]-x[pos]) <= r) vis[x[j]] = 1;
ans++;
}
printf("%d\n",ans);
}
int main(){
while(~scanf("%d%d",&r,&n)){
if(r == -1 && n == -1) break;
memset(vis,0,sizeof vis);
for(int i = 1;i <= n;i++) scanf("%d",x+i);
solve();
}
return 0;
}