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 }