CF 1353F - Decreasing Heights(枚举+DP)

题目:传送门

思路:如果直接DP,那么当前状态的不同的决策,会影响之后状态的决策 (每个点不同的决策,会导致之后的点选择之前的点时,权值不固定或者不一定能够得到最优解),有后效性;

   (1,1)->(n,m) 的路径上一定会经过n-m-2的点,而每个点是第几个经过是可以由 它的行数+列数-2 求得的。显然,根据贪心的思想,路径上至少有一个点的高度是不变,那么就可以枚举 高度不变的点 作为基准值,则就可以求得(1,1)的高度,并且这个高度是必须<= (1,1)的原高度 。按照这个策略,就可以免除dp的后效性,直接暴力dp即可。

 

 1 #include<bits/stdc++.h>
 2 /*
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<vector>
 7 #include<cctype>
 8 #include<queue>
 9 #include<algorithm>
10 #include<map>
11 #include<set>
12 */
13 #pragma GCC optimize(2)
14 using namespace std;
15 typedef long long LL;
16 typedef pair<int,int> pii;
17 typedef pair<double,double> pdd;
18 const int N=1e2+5;
19 const int M=1e4+5;
20 const LL inf=1e18;
21 const LL mod=1e9+7;
22 const double eps=1e-9;
23 const long double pi=acos(-1.0L);
24 #define ls (i<<1)
25 #define rs (i<<1|1)
26 #define fi first
27 #define se second
28 #define pb push_back
29 #define mk make_pair
30 #define mem(a,b) memset(a,b,sizeof(a))
31 LL read()
32 {
33     LL x=0,t=1;
34     char ch;
35     while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
36     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
37     return x*t;
38 }
39 LL a[N][N],dp[N][N];
40 LL n,m;
41 LL DP()
42 {
43     for(int i=1;i<=n;i++)
44         for(int j=1;j<=m;j++){
45             dp[i][j]+=min(dp[i-1][j],dp[i][j-1]);
46             dp[i][j]=min(inf,dp[i][j]);
47         }
48     return dp[n][m];
49 }
50 int main()
51 {
52     for(int i=1;i<N;i++) dp[i][0]=inf;
53     for(int j=1;j<N;j++) dp[0][j]=inf;
54     dp[0][1]=0;
55     int T=read();
56     while(T--)
57     {
58         n=read(),m=read();
59         for(int i=1;i<=n;i++)
60             for(int j=1;j<=m;j++)
61                 a[i][j]=read();
62         LL ans=inf;
63         //printf("%lld\n",inf);
64         for(int i=1;i<=n;i++)
65             for(int j=1;j<=m;j++)
66             {
67                 LL x=a[i][j]-i-j+2;//以a[i][j]为基准数,推导至 1,1 处的值;
68                 for(int l=1;l<=n;l++)
69                     for(int r=1;r<=m;r++)
70                         if(a[l][r]-l-r+2>=x) dp[l][r]=a[l][r]-x-l-r+2;
71                         else dp[l][r]=inf;
72                 ans=min(DP(),ans);
73             }
74         printf("%lld\n",ans);
75     }
76     return 0;
77 }
View Code

 

posted @ 2020-05-15 15:49  DeepJay  阅读(372)  评论(0编辑  收藏  举报