zoukankan      html  css  js  c++  java
  • pku1042 Gone Fishing

    黑书中的经典题:枚举+贪心
    把每钓5分钟鱼称为钓一次鱼。首先枚举John需要走过的池塘的数目X,即从池塘1走到池塘X。减去路上花去的时间T=sum(Ti) i=1...X-1,这样我们可以认为John能从一个池塘"瞬间转移"到另一个池塘,即在任意一个时刻都可以在池塘1到池塘X中任选一个钓一次鱼(很重要)。现在采用贪心策略,每次选择鱼最多的池塘钓一次鱼。对于每个池塘来说,由于在任何时候鱼的数目只和John在该池塘里钓鱼的次数有关,和钓鱼的总次数无关,所以这个策略是最优的。假设一共允许钓k次鱼,那么每次在N个池塘中选择鱼最多的一个钓。总的时间复杂度为O(kn^2)。(黑书中的解释)

     在最后的结果中,第一个最大值所对应的在每个池塘的钓鱼时间为题目要求的情况,因为如果John在后面的池塘钓了鱼,那么前面相应的时间就会减少。最后注意池塘中没有鱼的情况。

    具体见代码

    #include<stdio.h> 
    #include<string.h> 
    #include<stdlib.h> 
    #define MAXN 26 
    int main() 
    {    
    int n, h, tmp, sum, max;    
    int i, j, k, p;    
    int F[MAXN], f[MAXN], d[MAXN], t[MAXN] = {0}, ans[MAXN], ANS[MAXN];  
    // f[MAXN]保存每次湖泊剩下的鱼,ans[MAXN]保存每次枚举中各个湖泊呆的时间,ANS[MAXN]表示每次枚举后的在湖泊呆的最佳时间
    while (scanf("%d", &n) != EOF && n)   
    {       
    scanf("%d", &h);      
    h *= 12;        
    for (i = 0; i < n; i++)           
    scanf("%d", &F[i]);       
    for (i = 0; i < n; i++)            
    scanf("%d", &d[i]);        
    for (i = 1; i < n; i++)        
    {            
    scanf("%d", &tmp);            
    t[i] = tmp + t[i-1];    //到达第i个湖所用的时间    
    }       
    memset(ANS, 0, sizeof(ANS));      
    for (max = 0, i = 1; i <= n; i++)   // 枚举需要走过的湖泊的数目
    {            
    memset(ans, 0, sizeof(ans));             
    for (j = 0; j < i; j++)                
    f[j] = F[j];   //每次循环时,要恢复湖泊中原有的鱼的数目          
    for (j = 0, sum = 0; j < h - t[i-1]; j++)   //h-t[i-1]表示可以钓的次数         
    {                
    for (p = 0, k = 1; k < i; k++) //每次选一个鱼最多的湖泊钓一次鱼                  
    if (f[k] > f[p])                        
    p = k;                
    if (f[p] <= 0)         //该湖泊剩下的鱼少于零时,将剩下的所有时间都加到呆在第一个湖泊的时间上        
    {                    
    ans[0] += h - t[i-1] - j;                    
    break;                
    }                
    sum += f[p];               
    f[p] -= d[p];               
    ans[p]++;     //累加在该湖呆的时间       
    }            
    if (sum > max)             
    {                
    max = sum;                
    memcpy(ANS, ans, sizeof(ans));            
    }            
    if (sum == max)            
    {                
    for (j = 0; j < i; j++)                    
    if (ans[j] != ANS[j])                      
    break;                
    if (ans[j] > ANS[j])   //钓的鱼的数目相同时,选最近的湖泊呆比较长的时间                
    memcpy(ANS, ans, sizeof(ans));            
    }       
    }         
    for (i = 0; i < n - 1; i++)             
    printf("%d, ", ANS[i]*5);         
    printf("%d\nNumber of fish expected: %d\n\n", ANS[n-1]*5, max);     
    }     
    return 0; 
    }
    
  • 相关阅读:
    实战:垂直电商如何撬动“女人腰包”
    谈谈项目收尾
    项目管理心得:一个项目经理的个人体会、经验总结
    IT项目经理沟通技巧的重要性
    项目跟踪:项目跟踪要跟踪什么呢?
    会员营销,你真的做到了吗?
    Git入门——基础知识问答
    文摘:威胁建模(STRIDE方法)
    写在2015年工作的第一天
    简化工作——我的bat文件
  • 原文地址:https://www.cnblogs.com/nanke/p/2117524.html
Copyright © 2011-2022 走看看