• 回溯——oj1172 健康的荷斯坦奶牛


      花了一个多小时的时间搞定了这道题= =

      给出题面:

      很明显这道题是一道搜索的题,我用的是dfs+回溯。暴力的方法是设置一个计数器,如果满足条件时就进入下一重dfs,每次都判断是否达到要求,如果所用的肥料数最小的话就更新数组,这样的话可以拿下80%的数据,但仔细算算,如果是极限数据的话,需要进行15重dfs,每重都有一个二重循环,这样的话时间复杂度大概是(15*15)^15,很明显这样会超时,这时候需要做优化。

      仔细想想,每重dfs都是从数组的起点开始搜索,但实际上搜索的时候做了许多次重复,所以用了大部分的时间做了重复的操作,那具体应该怎么办呢?很显然,因为每次都是从数组起点开始搜索,所以上一重dfs中所搜索到的数的之前的数都是做的重复操作,那么可以建立一个指针,指针指向上一重dfs中搜索到的位置,在本次搜索中从指针的下一位开始搜索即可。

      此外还有一点可优化:因为要求输出使用饲料的最小数量,所以可以进行特判,当搜索的次数大于已经搜索到的最小次数时return即可。

      代码如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 int V,v[31],G,g[31][31],ans=9999,n[31];
     6 bool flag,f[31],vitamin[31];
     7 void dfs(int num,int place)
     8 {
     9     if (num>=ans)    return;
    10     flag=true;
    11     for (int i=1;i<=V;i++)
    12         if (v[i]>n[i])    {flag=false;    break;}
    13     if (flag)
    14     {
    15         if (num<ans)
    16         {
    17             ans=num;
    18             for (int i=1;i<=G;i++)
    19                 f[i]=vitamin[i];
    20         }
    21     }
    22     else
    23         for (int i=place+1;i<=G;i++)
    24         {
    25             if (!vitamin[i])
    26             {
    27                 for (int j=1;j<=V;j++)
    28                     n[j]+=g[i][j];
    29                 vitamin[i]=true;
    30                 dfs(num+1,i);
    31                 vitamin[i]=false;
    32                 for (int j=1;j<=V;j++)
    33                     n[j]-=g[i][j];
    34             }
    35         }
    36 }
    37 int main()
    38 {
    39     //freopen("add.in","r",stdin);
    40     //freopen("add.out","w",stdout);
    41     memset(n,0,sizeof(n));
    42     memset(vitamin,false,sizeof(vitamin));
    43     memset(f,false,sizeof(f));
    44     scanf("%d",&V);
    45     for (int i=1;i<=V;i++)
    46         scanf("%d",&v[i]);
    47     scanf("%d",&G);
    48     for (int i=1;i<=G;i++)
    49         for (int j=1;j<=V;j++)
    50             scanf("%d",&g[i][j]);
    51     dfs(0,0);
    52     printf("%d ",ans);
    53     for (int i=1;i<=G;i++)
    54         if (f[i])
    55             printf("%d ",i);
    56     return 0;
    57 }
    AC代码

      

  • 相关阅读:
    Go语言通道(chan)——goroutine之间通信的管道
    GO语言数组,切片,MAP总结
    GO数组
    GO切片
    GO语言测试
    GO语言html模板
    Go语言中defer语句使用小结
    微信小程序 某个页面直接返回首页
    小程序常用变量
    bzoj1030
  • 原文地址:https://www.cnblogs.com/hinanawitenshi/p/6397300.html
Copyright © 2020-2023  润新知