zoukankan      html  css  js  c++  java
  • dfs-hdu-4620-Fruit Ninja Extreme

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4620

    题目大意:

    切水果。给n刀,每刀的时间,每刀切的水果的种类。求能切的最多的刀数,使得每相邻的两刀时间差不超过给定的w.前面切了的水果不能再切,每刀至少要切不少于三个的新的水果。

    解题思路:

    直接一个一个的暴搜的话会超时。

    这里从每相邻两刀时间间隔不能超过w来考虑剪枝。问题抽象出来就是从给定的刀中选,相邻的选的话,不如按时间排序从小到大选,这样的效果更好,而且还可以剪枝。

    本题排序剪枝很关键。

    代码:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<stack>
    #include<list>
    #include<queue>
    #define eps 1e-6
    #define INF 0x1f1f1f1f
    #define PI acos(-1.0)
    #define ll __int64
    #define lson l,m,(rt<<1)
    #define rson m+1,r,(rt<<1)|1
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    
    
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    
    int hav[220]; //hav[i]表示已经切了的水果i
    int ti[35],num[35],fru[35][12],pos[35];
    int n,m,w;
    
    struct Node
    {
       int sa[35];
       int cnt;
    }ans,temp;
    
    //对时间进行排序后,可以大大剪枝。
    void dfs(int cur)
    {
       if(temp.cnt>ans.cnt)
          ans=temp;
       if(n-cur+temp.cnt<=ans.cnt)//这个剪枝很关键
          return ;
       for(int i=cur+1;i<=n;i++) //排序后可以剪枝
       {
          int pp=pos[i];
          int aa[12];
          if(temp.cnt&&ti[pp]-ti[pos[cur]]>w) //如果前面至少选了一个
             break;
          int sum=0; //前面一个都没选的话,任何一个都可以作为第一个
          for(int j=1;j<=num[pp];j++)
          {
             aa[j]=hav[fru[pp][j]];
             if(!aa[j])
                sum++;
          }
          if(sum<3)
             continue;
          for(int j=1;j<=num[pp];j++)
             hav[fru[pp][j]]|=1;
    
          temp.sa[++temp.cnt]=pp;
          dfs(i);
          temp.cnt--;
          for(int j=1;j<=num[pp];j++)
             hav[fru[pp][j]]=aa[j];
       }
    }
    bool cmp(int a,int b)
    {
       return ti[a]<ti[b];
    }
    int main()
    {
       int t;
       scanf("%d",&t);
       while(t--)
       {
          scanf("%d%d%d",&n,&m,&w);
          for(int i=1;i<=n;i++)
          {
             scanf("%d%d",&num[i],&ti[i]);
             for(int j=1;j<=num[i];j++)
                scanf("%d",&fru[i][j]);
             pos[i]=i;
          }
          sort(pos+1,pos+n+1,cmp); //对时间进行排序
          ans.cnt=0,temp.cnt=0;
          memset(hav,0,sizeof(hav));
          dfs(0);
          printf("%d
    ",ans.cnt);
          sort(ans.sa+1,ans.sa+ans.cnt+1);//输出按升序来
          if(!ans.cnt)
             continue;
          printf("%d",ans.sa[1]);
          for(int i=2;i<=ans.cnt;i++)
             printf(" %d",ans.sa[i]);
          putchar('
    ');
       }
       return 0;
    }
    
    


  • 相关阅读:
    简单编码解码学习
    如何把SQLServer数据库从高版本降级到低版本?
    快速读取csv平面文件,并导入数据库,简单小工具
    数据流处理数据
    配置文件的几种读取方式
    常用webservice接口地址
    路径转换
    Tornado与JS交互工作
    测试技术发展之我见
    移动测试人员的未来:测试开发技术的融合
  • 原文地址:https://www.cnblogs.com/pangblog/p/3285852.html
Copyright © 2011-2022 走看看