题意:给定一个栅栏,每次涂一行或者一列,问最少几次能够涂完
题解:分治算法+DP思想,每次的状态从竖着涂和横着涂中选择,同时向更高的部分递归计算。
1 #include<iostream>
2 #include<algorithm>
3 #include<cstdio>
4 #include<climits>
5 using namespace std;
6 int a[5001];
7 int f[5001][5001];
8 void cal(int l,int r,int v)
9 {
10 f[l][r]=r-l+1;
11 if(l==r)
12 {
13 return;
14 }
15 int tip=INT_MAX;
16 for(int i=l;i<=r;i++)
17 {
18 tip=min(tip,a[i]);
19 }
20 int ans=tip-v;
21 for(int i=l;i<=r;i++)
22 {
23 if(a[i]==tip)
24 {
25 continue;
26 }
27 int j;
28 for(j=i;j<=r;j++)
29 {
30 if(j==r)
31 {
32 break;
33 }
34 if(a[j+1]==tip)
35 {
36 break;
37 }
38 }
39 cal(i,j,tip);
40 ans+=f[i][j];
41 i=j+1;
42 }
43 f[l][r]=min(ans,f[l][r]);
44 return ;
45 }
46 int main()
47 {
48 int n;
49 scanf("%d",&n);
50 for(int i=1;i<=n;i++)
51 {
52 scanf("%d",&a[i]);
53 }
54 cal(1,n,0);
55 printf("%d",f[1][n]);
56 return 0;
57 }