自己看之區間DP

//菜雞製作,看的時候可能三目運算符略煩;;;

區間DP入門題:Brackets

地址:http://59.77.139.92/Problem.jsp?pid=1463

分析(對區間DP的代碼原理進行分步解析):

for(k=1; k<L; k++)
{
    for(i=0, j=k; j<L; i++, j++)
    {
        if(s[i]=='['&&s[j]==']'||s[i]=='('&&s[j]==')')
            dp[i][j]=dp[i+1][j-1]+2;
        for(x=i; x<j; x++)
            dp[i][j]=max(dp[i][j], dp[i][x]+dp[x+1][j]);
    }
}

樣例:()()()


變量是一一對應的應該;

 

區間DP原理就可以理清楚了。

然後我們看一下這題:刺激的摩托飛艇

地址:http://59.77.139.92/Problem.jsp?pid=2382

這一題求最小拆除路線實際上就是求最大不相交路線的數量, 也就是和上面那一題一模一樣,但是這一題變通的地方在於dp數組一開始就要賦值,相連則dp[i][j]=1, 其他的地方完全可以照搬

#include<stdio.h>
#define max(a, b) a>b?a:b
int n, i, j, k, l, dp[110][110], a;
int main( )
{
    scanf("%d", &n);
    while(n--)
        scanf("%d%d", &j, &k), j>k?dp[k][j]=1:dp[j][k]=1;
    for(k=2, n=101; k<n; k++)
        for(i=1, j=k; j<n; j++, i++)
        {
            for(l=i+1, a=0; l<j; l++)
                a=max(a, dp[i][l]+dp[l][j]);
            dp[i][j]+=a;
        }
    printf("%d\n", dp[1][100]);
}

例三:石子合併

地址:http://59.77.139.92/Problem.jsp?pid=2385

這一題的區別點就是石子是環狀的,那麼我們就可以簡單的對數組進行延長操作來求, 其他核心基本上不變

#include<stdio.h>
#define min(a, b) a<b?a:b
int dp[605][605], i, j, k, l, n, a[605], sum[605];
int main( )
{
    scanf("%d", &n);
    for(i=0; i<n; i++)
        scanf("%d", &a[i]), i?sum[i]=a[i]+sum[i-1]:sum[i]=a[i];///sum數組記錄前綴和
    for(i=n; i<2*n; i++)
        a[i]=a[i-n], sum[i]=sum[i-1]+a[i];///增長
    for(k=1; k<n; k++)
        for(i=0, j=k; j<2*n; i++, j++)
            for(l=i, dp[i][j]=0x3f3f3f; l<j; l++)
                dp[i][j]=min(dp[i][j], dp[i][l]+dp[l+1][j]+sum[j]-sum[i-1]);
    for(i=0, j=0x3f3f3f; i<n; i++)
        if(j>dp[i][i+n-1]&&dp[i][i+n-1])
            j=dp[i][i+n-1];
    printf("%d\n", j);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章