Found a good article, unfortunately found some places have typesetting problems. So changed, and added some of their own content.
Original link
A summary of the interval DP and its variable ring DP.
First, let's start with an example.
Stone Merge Title Description Description
There are n heap of stones in a row, each pile of stones have a weight of w[i], each merge can merge adjacent two piles of stones, the cost of a merger is the weight of two piles of stone and w[i]+w[i+1]. Ask what sort of merger sequence it takes to minimize the total merger cost.
Enter a description input Description
First line an integer n (n<=100)
Second row n integers w1,w2...wn (wi <= 100)
Outputs description Output Description
An integer representing the minimum consolidation cost
Sample input to sample
4
4 1 1 4
Sample output Sample Outputs
18
Interval DP model Obviously, the characteristic is that the given data is a chain or a ring (ring DP).
Partitioning questions:
We seek the minimum combined cost of the interval \ ([1,n]\) , while \ (dp[1][n]\) must be a combination of two segments ( dp[1][n] = {Dp[1][k]+dp[k+1][n]+sum[l][r ]}\)
Overriding the DP equation:\ (Dp[1][n] = {Dp[1][k]+dp[k+1][n] + sum[n]-sum[0]} (1\le k<n) \)
Because we don't know which part of the 1,n]\ is eventually merged, we are bound to enumerate breakpoints \ (k\).
We find that we need to calculate \ ([1,n]\) when we have completed the calculation of \ ([ 1,k],[k+1,n]\)
So before we enumerate to \ (n\), we must first calculate the interval in front of it. Then starting from N to enumerate the left endpoint, such as the calculation \ ([1,5]\) interval and the breakpoint enumeration to 3, we must have calculated the interval \ ([1,3]\) and interval \ ([4,5]\). The interval [1,3] is good, because our R is along the enumeration, the interval \ ([4,5]\) to calculate in front of it, the inner loop counter enumeration. (See Code)
We sum up the general equation \ (Dp[l][r] = {DP[L][K]+DP[K+1][R]+SUM[R]-SUM[L-1]} (l\le k\le r) \)
State definition \ (dp[l][r]\): The minimum cost of the interval \ ([l,r]\) Merge (the state must be two-dimensional, because we want to represent an interval in which the characteristics of the interval are represented by the left/right boundary)
The code demonstrates the following:
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespaceStdintn,w[101];intf[101][101];//f[i][j] Represents the minimum cost of the interval [i,j] mergerintsum[101] ;combined cost of preprocessing i→j (reduces algorithmic complexity)inline voidDP () { for(intj=2; j<=n; J + +) for(intK= (-1; i>=1; i--) {f[i][j]=1e7;//define a maximum value for(intK=i; k<j; k++) F[i][j] = min (F[i][j],f[i][k] + f[k +1][J] + sum[j]-sum[i-1]);//State transfer equation F[i][j] = min{f[i][k] + f[k + 1][j] + sum[j]-sum[i-1]} | I <= K < J}}intMain () {scanf ("%d", &n); for(intI=1; i<=n; i++) {scanf ("%d", &w[i]); Sum[i]=sum[i-1]+w[i]; } DP (); printf"%d", f[1][n]);return 0;}
Of course, we have another way of writing. Describing the state of an interval, we can also use the left endpoint + length to represent. Of course, the state definition is still the same (because \ (dp[l][l+len]\) is equivalent to \ (dp[l][r]\) when logging, but the way the enumeration is to be changed. It is not written here, only the core part.
The following code of execution logic and a little difference above, first of all adjacent two segments of the merger cost, and then calculate any adjacent 3-segment merger cost.
Because we are in the 3 paragraph, for example \ ([1,3]\) we have calculated \ ([1,2]\),\ ([2,3]\) the combined cost, so can be directly recursive.
for(int2//长度 for(int1; l+len-1//左端点 { int r = l+len-1; for(int//断点 dp[l][r] = max(dp[l][r],dp[l][k]+dp[k+1][r]+sum[r]-sum[l-1]); }
The answer is \ (dp[1][n]\).
Interval DP is generally written in these two forms, choose a way you like to write down. State definitions are generally two-dimensional [l,r]
Okay, and then we'll look at an example.
[NOI1995] Stone merger title description
Placing n heaps of stones around a circular playground is now a sequence of stones to be merged into a pile. The rule is that only the adjacent 2 stacks can be merged into a new pile at a time, and the new pile of stones is counted as the score of that merger.
In this paper, we design 1 algorithms to calculate the minimum score and the maximum score of combining n heap stones into 1 piles.
Input output Format input format:
The 1th line of data is a positive integer n,1≤n≤100, which indicates that there are n heap stones. The 2nd line has n number, which indicates the number of stones per heap.
Output format:
Output total 2 lines, 1th behavior minimum score, 2nd behavior maximum score.
Input and Output Sample input example # #:
4
4 5 9 4
Sample # # of output:
43
54
The data is changed from chain to ring, can't we handle it?
Here's a trick called "broken rings for chains."
Copy the Chain one times a[i+n] = A[i]
We then control the length of the enumeration by N. Look at the code implementation.
At the end of the answer, enumerate the beginning and fixed length \ (n\),\ (dp[l][l+n-1] (1\le l\le n) \).
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespaceStdintn,w[101];intf[201][201];//f[i][j] Represents the minimum cost of the interval [i,j] mergerintg[201][201];//f[i][j] represents the maximum cost of an interval [i,j] mergerintsum[201] ;combined cost of preprocessing i→j (reduces algorithmic complexity)intans_min=1e7;intans_max=0;inline voidDP () { for(intj=2; j<=n+n; J + +) for(intI=j-1; i>=1&&j-i<n; i--) {f[i][j]=1e7;//define a maximum value for(intK=i; k<j; k++) {F[i][j] = min (F[i][j],f[i][k] + f[k +1][J] + sum[j]-sum[i-1]);//State transfer equation F[i][j] = min{f[i][k] + f[k + 1][j] + sum[j]-sum[i-1]} | I <= K < JG[I][J] = max (G[i][j],g[i][k] + g[k +1][J] + sum[j]-sum[i-1]); }if(Ans_max<g[i][j]) ans_max=g[i][j]; }}intMain () {scanf ("%d", &n); for(intI=1; i<=n; i++) {scanf ("%d", &w[i]); W[i+n]=w[i]; } for(intI=1; i<=2*n; i++) {Sum[i]=sum[i-1]+w[i]; } DP (); for(intI=1; i<=n; i++) {if(Ans_min>f[i][i+n-1]) Ans_min=f[i][i+n-1]; } printf ("%d\n", ans_min); printf"%d\n", Ans_max);return 0;}
The above code is written in the first way, and you can easily write it in the second way (left end + length). The code is not given here.
Ah, just write a copy, OK, or put the code out. But I hope you think seriously, DP's question see Code and equations may be easy to understand, but the difficulty is to think of code and equations, or define the state. Beginners can learn first, after a period of time to do. The person who is reviewing does not look at the code.
#include <cstdio>#include <iostream>#include <cmath>#include <algorithm>#include <cstring>using namespaceStdintNintw[ -],sum[ -];intf[ -][ -];intg[ -][ -];intMain () {scanf ("%d", &n); for(intI=1; i<=n; i++) {scanf ("%d", &w[i]); W[i+n] = W[i]; } for(intI=1; i<=2*n; i++) Sum[i]=w[i]+sum[i-1]; for(intLen =2; Len <= N; len++) { for(intL=1; l<=2*n-len+1; l++)//Be careful here{intr = L+len-1; f[l][r]=1e9; for(intK=l; k<r; k++) {F[l][r] = min (f[l][r],f[l][k]+f[k+1][r]+sum[r]-sum[l-1]); G[l][r] = max (g[l][r],g[l][k]+g[k+1][r]+sum[r]-sum[l-1]); } } }intAns_max =0, ans_min =1e9; for(intI=1; i<=n; i++) {ans_min = min (ans_min,f[i][i+n-1]); Ans_max = Max (ans_max,g[i][i+n-1]); } cout<<ans_min<<endl; cout<<ans_max;return 0;}
Reprint + Pruning: Algorithm explained dynamic programing--interval DP [variant: Ring DP]