poj1042(黑书第一道贪心题)

题意就不说了,主要讲讲思路以及注意的地方。

思路:是按黑书上给出的思路编的,主要是贪心+枚举。因为每个池塘只能走一次,可以枚举前1,2,3,.....n个池塘之间所能钓的最大鱼数。我们可以将路程一次性处理完毕,这样就可以瞬移......每次瞬移到鱼最多的池塘钓鱼就好。有点遗憾,他们说可以用dp做,想了许久,没想明白dp怎么做

注意:这道题目思路很简单,倒是细节处理很麻烦,我因为没有想到一个池塘里面的鱼还可以为负数,就贡献了6次wa.......

还得注意:所有池塘鱼为0;不需要走路就可以到下一个池塘;在某种状态下,这一个状态的最大鱼数等于前面的状态中的最大鱼数,这时候要考虑这种状态下是否有某一个池塘的编号小于前一个池塘或者,是不是同一编号下,这种状态下的那个池塘比前面状态下鱼数要大......可能没有说清楚,具体看代码

1:钓鱼次数大于0才进去循环,而不是!=0时


2:当每次求得的sum和最终结果ans相比时,大于ans直接复制,如果等于的话则一定要比较哪个结果中编号小的池塘呆的时间多。

3:当鱼的数目为负数时,直接将数目变成0,而不是负数(没想通为什么,但如果是负数就是不AC,写完这个我再好好研究下)

4:如果你是用排序的方法确定当前的最大值,最好自己写一个排序算法,因为你必须保证当前选的池塘的鱼的数目不仅是最多的,而且池塘的编号也要是最小的!!!直接用排序算法模板相当危险,我把插入排序改进了,重点是可能有很多值相等的情况,你必须保证你选择的池塘是编号最小的。虽说你可以每次从头搜索,找一个最大的,但会超时。

5:最终结果ans的初值应该是负数,因为很可能、不,是就是会有最终结果为0的情况,所以利用if(sum>ans)判断结果时,ans的初值要是负数

6:数据很变态很无耻,有di[i]=0的情况,鱼的数目不会减少;也有时间等于0的情况;显然也有f[i],t[i]=0的情况,好好想想是否都考虑到了,用数据测试一下就好了

7:输出格式算是个小问题吧,记得有两个回车,最后一个池塘木有逗号。

代码:

View Code
  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<queue>
  5 using namespace std;
  6 struct ss
  7 {
  8     friend bool operator<(const ss a,const ss b)
  9     {
 10         if(a.sum<b.sum)
 11         return 1;
 12         else if(a.sum==b.sum&&a.num>b.num)
 13         return 1;
 14         else
 15         return 0;
 16     }
 17     int num,sum,d;
 18 };
 19 struct
 20 {
 21     int sum,d;
 22 }s[50];
 23 int a[50],b[50],t[50];
 24 int main()
 25 {
 26     int n,h;
 27     while(scanf("%d",&n)>0&&n)
 28     {
 29         int tol=-10,tol1=0;
 30         memset(a,0,sizeof(a));
 31         scanf("%d",&h);
 32         h=h*12;
 33         for(int i=1;i<=n;i++)
 34         {
 35             scanf("%d",&s[i].sum);
 36             if(s[i].sum<0)
 37             s[i].sum=0;
 38         }
 39         for(int i=1;i<=n;i++)
 40         scanf("%d",&s[i].d);
 41         t[0]=t[1]=0;
 42         for(int i=2;i<=n;i++)
 43         scanf("%d",&t[i]);
 44         for(int i=1;i<=n;i++)
 45         {
 46             priority_queue<ss>q;
 47             int ht=h;
 48             tol1=0;
 49             memset(b,0,sizeof(b));
 50             for(int j=1;j<=i;j++)
 51             {
 52                 ss node;
 53                 node.num=j;
 54                 node.sum=s[j].sum;
 55                 node.d=s[j].d;
 56                 ht=ht-t[j];
 57                 if(node.sum>0)
 58                 q.push(node);
 59             }
 60             while(!q.empty()&&ht>0)
 61             {
 62                 ss node=q.top();
 63                 q.pop();
 64                 tol1+=node.sum;
 65                 node.sum-=node.d;
 66                 b[node.num]++;
 67                 ht--;
 68                 if(node.sum>0)
 69                 {
 70                     q.push(node);
 71                 }
 72             }
 73             if(tol1>=tol)
 74             {
 75                 if(tol1>tol)
 76                 {
 77                     tol=tol1;
 78                     if(ht>0)
 79                     b[1]+=ht;
 80                     for(int k=1;k<=n;k++)
 81                     {
 82                         a[k]=b[k];
 83                     }
 84                 }
 85                 else
 86                 {
 87                     if(ht>0)
 88                     b[1]+=ht;
 89                     for(int k=1;k<=n;k++)
 90                     {
 91                         if(a[k]>b[k])
 92                         break;
 93                         else if(a[k]<b[k])
 94                         {
 95                             for(int j=1;j<=n;j++)
 96                             a[j]=b[j];
 97                             break;
 98                         }
 99                     }
100                 }
101             }
102         }
103         for(int i=1;i<n;i++)
104         printf("%d, ",a[i]*5);
105         printf("%d\n",a[n]*5);
106         printf("Number of fish expected: %d\n\n",tol);
107     }
108     return 0;
109 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值