zoukankan      html  css  js  c++  java
  • NOIP模拟18 T2

    不知道为什么很多人拒绝这题打搜索。。。其实搜索在充分剪枝后时间是非常优秀的,不管数据怎样基本都可跑出

      首先一个显然结论:对于某种状态,他抓到的小精灵一定是一个连续的区间。

      因此我们可以枚举这个区间的左右端点,进行搜索,但是这样显然会T,我们考虑剪枝:

      1.可行性剪枝,当前时间大于最大时间直接return(废话)

      2.最优性剪枝,对于每种状态,我们用两个数组来记录出现这种状态所需要的最短时间,以及最短时间下的最优答案,若时间长答案还小,直接return

      3.确定枚举方向,如果上一步从左向右走,那么当前必然向左走。很显然,若继续向右走,与上一次枚举的有重复。

      4.一个比较玄学但是非常有用的剪枝:对于当前左右端点l,r,在枚举右端点时,从m处开始枚举到r+1,而不是从r+1枚举到m,左端点同理。看上去比较玄学,实际上是有一定原理的:若我们枚举到的端点离当前端点很近,那么会重复走很多位置,在大多数情况下浪费时间,往往无法得到最优解,而较远端点更可能获得更优的答案,结合剪枝2,会将较近端点剪掉,除去很多不必要搜索。

      综合以上,我们就可以得到一个时间碾压正解的搜索(欢迎造数据hack)

      附代码:

     1 #include<bits/stdc++.h>
     2 #define cri const register int
     3 using namespace std;
     4 int n,k,m,maxt,ans,ys[2005],yx[2005],f[105][105],ff[105][105];
     5 char v[105];
     6 inline int abs(int x){return x<0?-x:x;}
     7 struct jing{
     8     int a,b,t;
     9     friend bool operator < (jing a,jing b){
    10         return a.a<b.a;
    11     }
    12 }c[105];
    13 void dfs(cri ti,cri l,cri r,cri na,cri o){
    14     if(ti<maxt)ans=max(ans,na);
    15     if(ti>=maxt)return;
    16     if(ti>=f[l][r]&&na<=ff[l][r]){
    17         return;
    18     }
    19     if(f[l][r]>ti)f[l][r]=ti,ff[l][r]=na;
    20     if(o!=0){
    21         int sum=0;
    22         for(int i=m+1;i>=r+1;i--)
    23             if(ti+c[i].a-c[l].a<=c[i].t)
    24                 sum+=c[i].b;
    25         for(int i=m+1;i>=r+1;i--){
    26             if(ti+c[i].a-c[l].a<=c[i].t){
    27                 dfs(ti+c[i].a-c[l].a,l,i,na+sum,0);
    28                 sum-=c[i].b;
    29             }
    30         }
    31     }
    32     if(o!=1){
    33         int sum=0;
    34         for(int i=l-1;i>=1;i--){
    35             if(ti+c[r].a-c[i].a<=c[i].t){
    36                 sum+=c[i].b;
    37             }
    38         }
    39         for(int i=1;i<=l-1;i++){
    40             if(ti+c[r].a-c[i].a<=c[i].t){
    41                 dfs(ti+c[r].a-c[i].a,i,r,na+sum,1);
    42                 sum-=c[i].b;
    43             }
    44         }
    45     }
    46 }
    47 inline int read(){
    48     int x=0;
    49     char ch=getchar();
    50     while(ch<'0'||ch>'9')ch=getchar();
    51     while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=getchar();
    52     return x;
    53 }
    54 int main(){
    55     memset(f,0x3f,sizeof(f));
    56     scanf("%d%d%d",&n,&k,&m);
    57     for(int i=1;i<=m;i++)
    58         c[i].a=read(),c[i].b=read(),c[i].t=read(),maxt=max(maxt,c[i].t);
    59     c[m+1].a=k;c[m+1].b=0,c[m+1].t=0;
    60     maxt++;
    61     sort(c+1,c+m+2);
    62     for(int i=1;i<=m+1;i++)
    63         ys[c[i].a]+=c[i].b,yx[c[i].a]=i;
    64     dfs(1,yx[k],yx[k],ys[k],-1);
    65     printf("%d",ans);
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    win中使用curl上传文件报错
    S2-052
    S2-048
    S2-045、S2-046
    S2-033、S2-037
    S2-032
    S2-029
    day12-python之深灰魔法
    day10-11-python基础之字符串
    day09-python基础
  • 原文地址:https://www.cnblogs.com/hzoi-cbx/p/11342723.html
Copyright © 2011-2022 走看看