自己看之区间DP
//菜鸡制作,看的时候可能三目运算符略烦;;;
区间DP入门题:Brackets
地址:http://59.77.139.92/Problem.jsp?pid=1463
分析(对区间DP的代码原理进行分步解析):
1 for(k=1; k<L; k++) 2 { 3 for(i=0, j=k; j<L; i++, j++) 4 { 5 if(s[i]=='['&&s[j]==']'||s[i]=='('&&s[j]==')') 6 dp[i][j]=dp[i+1][j-1]+2; 7 for(x=i; x<j; x++) 8 dp[i][j]=max(dp[i][j], dp[i][x]+dp[x+1][j]); 9 } 10 }
样例:()()()
变量是一一对应的应该;
区间DP原理就可以理清楚了。
然后我们看一下这题:刺激的摩托飞艇
地址:http://59.77.139.92/Problem.jsp?pid=2382
这一题求最小拆除路线实际上就是求最大不相交路线的数量, 也就是和上面那一题一模一样,但是这一题变通的地方在于dp数组一开始就要赋值,相连则dp[i][j]=1, 其他的地方完全可以照搬
1 #include<stdio.h> 2 #define max(a, b) a>b?a:b 3 int n, i, j, k, l, dp[110][110], a; 4 int main( ) 5 { 6 scanf("%d", &n); 7 while(n--) 8 scanf("%d%d", &j, &k), j>k?dp[k][j]=1:dp[j][k]=1; 9 for(k=2, n=101; k<n; k++) 10 for(i=1, j=k; j<n; j++, i++) 11 { 12 for(l=i+1, a=0; l<j; l++) 13 a=max(a, dp[i][l]+dp[l][j]); 14 dp[i][j]+=a; 15 } 16 printf("%d\n", dp[1][100]); 17 }
例三:石子合并
地址:http://59.77.139.92/Problem.jsp?pid=2385
这一题的区别点就是石子是环状的,那么我们就可以简单的对数组进行延长操作来求, 其他核心基本上不变
1 #include<stdio.h> 2 #define min(a, b) a<b?a:b 3 int dp[605][605], i, j, k, l, n, a[605], sum[605]; 4 int main( ) 5 { 6 scanf("%d", &n); 7 for(i=0; i<n; i++) 8 scanf("%d", &a[i]), i?sum[i]=a[i]+sum[i-1]:sum[i]=a[i];///sum数组记录前缀和 9 for(i=n; i<2*n; i++) 10 a[i]=a[i-n], sum[i]=sum[i-1]+a[i];///增长 11 for(k=1; k<n; k++) 12 for(i=0, j=k; j<2*n; i++, j++) 13 for(l=i, dp[i][j]=0x3f3f3f; l<j; l++) 14 dp[i][j]=min(dp[i][j], dp[i][l]+dp[l+1][j]+sum[j]-sum[i-1]); 15 for(i=0, j=0x3f3f3f; i<n; i++) 16 if(j>dp[i][i+n-1]&&dp[i][i+n-1]) 17 j=dp[i][i+n-1]; 18 printf("%d\n", j); 19 }