[dp] Jzoj P5770 可爱精灵宝贝

Description

Branimirko是一个对可爱精灵宝贝十分痴迷的玩家。最近,他闲得没事组织了一场捉精灵的游戏。游戏在一条街道上举行,街道上一侧有一排房子,从左到右房子标号由1到n。
刚开始玩家在k号房子前。有m个精灵,第i只精灵在第A[i]栋房子前,分值是B[i],以及它在T[i]秒内(含)存在,之后消失。Branimirko可以选择移动至相邻的房子,耗时1秒。抓住精灵不需要时间,精灵被抓住后消失。时间从第1秒开始。Branimirko能最多获得多少分值和。
 
 

Input

输入的第1行为三个正整数n,k,m。
接下来m行描述精灵的信息,分别为A[i],B[i],T[i]。
 

Output

输出Branimirko能最多获得多少分值和。
 
 

Sample Input

10 5 4
1 30 4
3 5 7
7 10 12
9 100 23
 

Sample Output

115
 
 

Data Constraint

20%的数据:m≤10
40%的数据:m≤20
k≤n≤1000,m≤100,A[i] ≤N,B[i] ≤100,T[i] ≤2000,所有数为正整数。
 
 

Hint

很遗憾,它恰好不能抓住在一号房子前的精灵。
如果T[1]改成5,答案就是145

90%题解

  • 其实就是一个水法,只考虑一个折回的话
  • 直接枚举到左端点折回或到右端点折回
  • 暴力判断

100%题解

  • 对于数据,是不只有一个折回的,因为会存在一种这样的情况:
  • 向左走到某个点后,向右边恰好有一个点的时间可行,然后到了这个点后,左边又有一个点恰好时间可行,这样就不止一个折回了
  • 考虑一下dp
  • 设f[t][l][r][0/1]表示 当前时间为t 走过的区间为[l,r] 0表示在l 1表示在r 的最大分数
  • 那么对于[l,r]中间的点可以不用管,这时可以肯定的
  • 考虑如何转移,如果当前在l,可以考虑走到l-1或者到r再走到r+1
  • 如果在r,可以考虑走到r+1或者走到l再走到l-1
  • 最后的ans就是在dp转移过程中求max

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 using namespace std;
 7 struct edge{int a,b,t;}e[1010];
 8 int f[2005][103][103][2],n,m,k,ans,mx,w;
 9 bool cmp(edge x,edge y){ return x.a<y.a; }
10 int dis(int x,int y) { return abs(e[x].a-e[y].a); }
11 int main()
12 {
13     //freopen("go.in","r",stdin);
14     //freopen("go.out","w",stdout);
15     scanf("%d%d%d",&n,&k,&m);
16     for (int i=1;i<=m;i++) scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].t),mx=max(mx,e[i].t);
17     m++,e[m]=edge{k,0,mx};
18     sort(e+1,e+m+1,cmp);
19     memset(f,-63,sizeof(f));
20     for (int i=1;i<=m;i++)
21         if (e[i].a==k&&e[i].b==0) 
22             w=i;
23     f[0][w][w][0]=f[0][w][w][1]=0;
24     for (int i=w-1;i>=1;i--)
25     {
26         int tim=e[w].a-e[i].a;
27         f[tim][i][w][0]=f[dis(w,i+1)][i+1][w][0]+((tim<e[i].t)?e[i].b:0);
28         ans=max(ans,f[tim][i][w][0]);
29     }
30     for (int i=w+1;i<=m;i++)
31     {
32         int tim=e[i].a-e[w].a;
33         f[tim][w][i][1]=f[dis(i-1,w)][w][i-1][1]+((tim<e[i].t)?e[i].b:0);
34         ans=max(ans,f[tim][w][i][1]);
35     }
36     for (int i=1;i<=mx;i++)
37         for (int l=1;l<=w-1;l++)
38             for (int r=w+1;r<=m;r++)
39             {
40                 f[i][l][r][0]=max(f[max(i-dis(l,l+1),0)][l+1][r][0],f[max(i-dis(l,r),0)][l+1][r][1])+((i<e[l].t)?e[l].b:0);
41                 f[i][l][r][1]=max(f[max(i-dis(r-1,r),0)][l][r-1][1],f[max(i-dis(l,r),0)][l][r-1][0])+((i<e[r].t)?e[r].b:0);
42                 ans=max(ans,max(f[i][l][r][0],f[i][l][r][1]));
43             }
44     printf("%d",ans);
45     return 0;
46 }
原文地址:https://www.cnblogs.com/Comfortable/p/9433530.html