POJ 1160 Post Office (quadrangle inequality optimization)

Quadrilateral inequality

Function w satisfies

1: monotonicity interval comprises, for the \ (X1 <X2 <Y1 <Y2 \) , there are \ (W [X2] [Y1] <W [X1] [Y2] \)
2: quadrilateral inequality for \ (X1 <X2 <Y1 <Y2 \) , there are \ (w [x1] [y1 ] + w [x2] [y2] <w [x1] [y2] + w [x2] [y1] \)

The function m (which is the optimal choice) satisfies inequality quadrilateral.

For quadrilateral satisfy inequality function is monotone (x direction monotonously, y monotonically direction) can be determined by whether dp satisfies the inequality quadrilateral, may be used to optimize the transfer section

For the form \ (dp [i] [j ] = min (dp [i] [k] + dp [k + 1] [j]) (i \ leq k \ leq j) + w [i] [j] \) interval dp transfer generally complexity O (n ^ 3) is,
but if \ (dp [i] [j ] \) satisfies the inequality quadrangle, it \ (S [I] [J] \) (so dp [i] [j] is the smallest k) satisfies inequality quadrilateral, metastasis to O (n ^ 2) a
\ (dp [i] [j ] = min (dp [i] [k] + dp [k +1] [j]) (s [i] [j-1] \ leq k \ leq s [i + 1] [j]) + w [i] [j] \)

Stone merger

  • Meaning of the questions: a circle of stones, each can merge two adjacent, get a new stone, its weight and authority to the original two stones, the combined score for the note, asked to merge into a pile of stones around the minimum the maximum score
  • Thinking: DP range, the minimum value satisfying the inequality quadrangular, the maximum value is not satisfied, because a circle, run-off ring to the combined chain of 1 ~ 2n
using namespace std;
const int N = 200+10;

int n;
int a[N],sum[N];
int dp[N][N],s[N][N];
int ans1 = 1<<30,ans2= 0;
int main(){
    while(scanf("%d",&n)==1){
    for(int i=1;i<=n;++i)   scanf("%d",&a[i]),a[i+n]=a[i];
    for(int i=1;i<=n*2;++i) sum[i] = sum[i-1]+a[i];
    for(int i=1;i<=n*2;++i) dp[i][i]=0,s[i][i] = i;
    for(int len=2;len<=n;++len){
        for(int i=1;i+len-1<=n*2;++i){
            int j = i+len-1;
            dp[i][j] = 1<<30;
            for(int k=s[i][j-1];k<=s[i+1][j];++k){
                int val = dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1];
                if(val < dp[i][j]){
                    dp[i][j] = val;
                    s[i][j] = k;
                }
            }
        }
    }
    ans1 = dp[1][n];
    for(int i=1;i<=n;++i)   ans1 = min(ans1,dp[i][i+n-1]);
    for(int i=1;i<=n*2;++i) dp[i][i]=0;
    for(int len=2;len<=n;++len){
        for(int i=1;i+len-1<=n*2;++i){
            int j = i+len-1;
            dp[i][j] = 0;
            for(int k=i;k<j;++k){
                int val = dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1];
                if(val > dp[i][j]){
                    dp[i][j] = val;
                }
            }
        }
    }
    ans2 = dp[1][n];
    for(int i=1;i<=n;++i)   ans2 = max(ans2,dp[i][i+n-1]);
    printf("%d\n%d\n",ans1,ans2);   
    }
    return 0;
}

POJ 1160 Post Office

  • The meaning of problems: n points on a straight line, to be selected from the m points, each point for the minimum sum of the distance of the selected point
  • Thinking: l the first operator to choose only a distance r of the house, and then enumerate interval dp k, m-1 is selected from the front of a house, the house behind the gate 1, k requires optimization quadrilateral inequality

The current can be calculated by the front dis dis and a current position O (1)


const int N = 300+10, M = 32;

int n,m,pos[N],dis[N][N];   // i到j选一个点作为邮局最短距离
int dp[N][M],s[N][M];       // 1到i选j个点作为邮局的最短距离,和最优转移点

int main(){
    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;++i)   scanf("%d",&pos[i]);
    for(int i=1;i<=n;++i){
        dis[i][i] = 0;
        for(int j=i+1;j<=n;++j){    // 两点之间肯定要选中位数所在点
            dis[i][j] = dis[i][j-1] + pos[j] - pos[(i+j)>>1];   // dis只增加了右端点到中间点的距离
        }
    }
    for(int i=1;i<=n;++i)
        dp[i][1] = dis[1][i],s[i][1] = 0;   // 初始化  1到i选一个点的最短距离即为 dis[1][i], 而只选了一个点没有转移点
    //  s[j][i-1] <=  s[j][i] <= s[j+1][i]   j从大到小,i从小到大    
    for(int i=2;i<=m;++i){  // 当前选了几个点
        s[n+1][i] = n;      // 这个值不会被计算,但要被用到,赋为n
        for(int j=n;j>i;--j){   // 当前有几个房子
            dp[j][i] = 1<<30;
            for(int k=s[j][i-1];k<=s[j+1][i];++k){
                int val = dp[k][i-1] + dis[k+1][j];
                if(dp[j][i]> val) dp[j][i] = val, s[j][i] = k;
            }
        }
    }
    printf("%d\n",dp[n][m]);
}

Guess you like

Origin www.cnblogs.com/xxrlz/p/11449466.html