[前缀和][dp] Jzoj P5873 小p的属性

Description

 

Input

Output

 

Sample Input

2 4
2 1 10
1 2 20
 

Sample Output

50
 

Data Constraint

题解

  • 把问题转化一下,就是在一个二维的平面上,有些点有权值,你每次都可以向右或者向上走,经过一个点后得到他的权值,并且每走一步都会再次加上他的权值,问你走k步的最大权值是多少
  • 我们发现他每次走都会走到某个点上,这样答案才会更优
  • 所以我们把所有点的横坐标纵坐标拿出来离散,然后插入点值,这样就可以不用枚举坐标了

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 struct edge { int x,y,z; }e[1010];
 6 int n,m,cnt1,cnt2,cnt;
 7 long long ans,f[1010][1010],g[1010][1010],l[1010],r[1010];
 8 int find1(int x)
 9 {
10     int L=1,R=cnt1;
11     while (L<=R)
12     {
13         int mid=(L+R)>>1;
14         if (l[mid]==x) return mid;
15         if (l[mid]<x) L=mid+1; else R=mid-1;
16     }
17 }
18 int find2(int x)
19 {
20     int L=1,R=cnt2;
21     while (L<=R)
22     {
23         int mid=(L+R)>>1;
24         if (r[mid]==x) return mid;
25         if (r[mid]<x) L=mid+1; else R=mid-1;
26     }
27 }
28 int main()
29 {
30     freopen("growth.in","r",stdin);
31     freopen("growth.out","w",stdout);
32     scanf("%d%d",&n,&m);
33     for (int i=1;i<=n;i++)
34     {
35         int x,y,z;
36         scanf("%d%d%d",&x,&y,&z);
37         if (x+y>m) continue;
38         e[++cnt].x=x,e[cnt].y=y,e[cnt].z=z;
39         l[++cnt1]=x,r[++cnt2]=y;
40     }
41     sort(l+1,l+cnt1+1),sort(r+1,r+cnt2+1);
42     cnt1=unique(l+1,l+cnt1+1)-l-1,cnt2=unique(r+1,r+cnt2+1)-r-1;
43     for (int i=1;i<=cnt;i++) g[find1(e[i].x)][find2(e[i].y)]+=e[i].z;
44     for (int i=1;i<=cnt1;i++)
45         for (int j=1;j<=cnt2;j++)
46             g[i][j]+=g[i-1][j]+g[i][j-1]-g[i-1][j-1];
47     for (int i=1;i<=cnt1;i++)
48         for (int j=1;j<=cnt2;j++)
49             f[i][j]=g[i][j]+max(f[i-1][j]+(l[i]-l[i-1]-1)*g[i-1][j],f[i][j-1]+(r[j]-r[j-1]-1)*g[i][j-1]);
50     for (int i=1;i<=cnt1;i++)
51         for (int j=1;j<=cnt2;j++)
52             if (l[i]+r[j]<=m)
53                 ans=max(ans,f[i][j]+(m-l[i]-r[j])*g[i][j]);
54     printf("%lld",ans);
55 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9688527.html
今日推荐