1. 程式人生 > >51nod oj 1022 石子歸併 V2 【環形區間DP----四邊形不等式優化】

51nod oj 1022 石子歸併 V2 【環形區間DP----四邊形不等式優化】

題目傳送門:1022

四邊形不等式優化:

m[i,j]=min{m[i,k]+m[k,j]}(s[i,j-1]≤k≤s[i+1,j])

m[i,j]=min{m[i,k]+m[k,j]}(i≤k≤j)

s[i,j]表示i到j的最優分點

s[i,j-1]≤s[i,j]≤s[i+1,j]

怎麼證明某一題能不能用這個優化呢--

我---不會---

我就想

對於O( n^3 )演算法不行的就假設它能用四邊形不等式優化吧---

程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int shu[2020],dp[2020][1010],s[2020][1010],he[2020];
int main()
{
    int n;scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&shu[i]);
        shu[i+n]=shu[i];
    }
    he[0]=0;
    for (int i=1;i<=2*n;i++)
    he[i]=he[i-1]+shu[i];
    for (int i=1;i<=2*n;i++)  
        for (int j=1;j<=n;j++)  
            dp[i][j]=999999999;  
    for (int i=1;i<=n*2;i++)
    {
    	dp[i][0]=0;
    	dp[i][1]=0;
    	s[i][1]=i;
	}
    for (int k=2;k<=n;k++)
    {
        for (int i=1;i<=n;i++)
        	for (int j=s[i][k-1];j<=s[i+1][k-1];j++)//四邊形不等式優化
        		if (dp[i][k]>dp[i][j-i+1]+dp[j+1][k-j+i-1]+he[i+k-1]-he[i-1])
        		{
        			dp[i][k]=dp[i][j-i+1]+dp[j+1][k-j+i-1]+he[i+k-1]-he[i-1];
        			s[i][k]=j;
				}
		for (int i=1;i<=n;i++)
		{
			dp[i+n][k]=dp[i][k];
			s[i+n][k]=s[i][k]+n;
		}
    }
    int ans=666666666;
    for (int i=1;i<=n;i++)
    	ans=min(ans,dp[i][n]);
    printf("%d\n",ans);
    return 0;
}