zoukankan      html  css  js  c++  java
  • 四边形不等式例题完整解析(不加推导)

    P4767 [IOI2000]邮局

    dp方程:

    dp[i][j]=min{dp[k][j−1]+w(k+1,i)},k∈[0,i)

    #include<bits/stdc++.h>
    #define MAXN 3010
    #define N 310
    
    using namespace std;
    
    int V,P,X[MAXN],dp[MAXN][N];
    
    int w(int l,int r) {
    	int mid=l+r>>1,ans=0;
    	for(int i=l;i<mid;i++) ans+=X[mid]-X[i];
    	for(int i=mid+1;i<=r;i++) ans+=X[i]-X[mid];
    	return ans;
    }
    
    int main() {
    	cin>>V>>P;
    	for(int i=1;i<=V;i++) cin>>X[i];
    	
    	sort(X+1,X+V+1);
    	memset(dp,0x3f,sizeof(dp));
    	dp[0][0]=0;
    	for(int j=1;j<=P;j++) {
    		for(int i=1;i<=V;i++) {
    			for(int k=0;k<i;k++) {
    				dp[i][j]=min(dp[k][j-1]+w(k+1,i),dp[i][j]);
    			}
    		}
    	}
    
    	cout<<dp[V][P]<<endl;
    	
    	return 0;
    }
    

    我们发现对于w的预处理是n2的,而dp是n3的,很明显过不了数据,考虑优化;

    发现w是可以递归预处理的,时间复杂度n^3

    #include<bits/stdc++.h>
    #define MAXN 3010
    #define N 310
    
    using namespace std;
    
    int V,P,X[MAXN],dp[MAXN][N],w[MAXN][MAXN];
    
    void init() {
    	for(int l=1;l<=V;l++) {
    		w[l][l]=0;
    		for(int r=l+1;r<=V;r++) {
    			w[l][r]=w[l][r-1]+X[r]-X[l+r>>1];
    		}
    	}
    }
    
    int main() {
    	cin>>V>>P;
    	for(int i=1;i<=V;i++) cin>>X[i];
    	
    	init();
    	sort(X+1,X+V+1);
    	memset(dp,0x3f,sizeof(dp));
    	dp[0][0]=0;
    	for(int j=1;j<=P;j++) {
    		for(int i=1;i<=V;i++) {
    			for(int k=0;k<i;k++) {
    				dp[i][j]=min(dp[k][j-1]+w[k+1][i],dp[i][j]);
    			}
    		}
    	}
    
    	cout<<dp[V][P]<<endl;
    	
    	return 0;
    }
    

    发现没有什么别的方法可以优化了, 而且还是过不了数据范围,并且dp式子和四边形不等式的模板式特别像,我们先大胆猜测一下这个题用的是四边形不等式,打表来看一下w是否具有决策单调性

    #include<bits/stdc++.h>
    #define MAXN 3010
    #define N 310
    
    using namespace std;
    
    int V,P,X[MAXN],dp[MAXN][N],w[MAXN][MAXN];
    
    void init() {
    	for(int l=1;l<=V;l++) {
    		w[l][l]=0;
    		for(int r=l+1;r<=V;r++) {
    			w[l][r]=w[l][r-1]+X[r]-X[l+r>>1];
    		}
    	}
    }
    
    int main() {
    	cin>>V>>P;
    	for(int i=1;i<=V;i++) cin>>X[i];
    	
    	init();
    	sort(X+1,X+V+1);
    	memset(dp,0x3f,sizeof(dp));
    	dp[0][0]=0;
    	for(int j=1;j<=P;j++) {
    		for(int i=1;i<=V;i++) {
    			for(int k=0;k<i;k++) {
    				if(dp[i][j]>dp[k][j-1]+w[k+1][i])
    				cout<<k<<" ";
    				dp[i][j]=min(dp[k][j-1]+w[k+1][i],dp[i][j]);
    			}
    			cout<<'
    ';
    		}
    	}
    
    	cout<<dp[V][P]<<endl;
    	
    	return 0;
    }
    
    10 5
    1 2 3 6 7 9 11 22 44 50
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    
    1
    1
    1 3
    1 2 3
    1 2 3
    1 2 3
    1 2 3 7
    1 2 3 4 6 7 8
    1 2 3 4 5 6 7 8
    
    
    2
    2 3
    2 3
    2 3 5
    2 3 4 5
    2 3 4 5 7
    2 3 4 5 6 7 8
    2 3 4 5 6 7 8
    
    
    
    3
    3
    3 5
    3 4 5 6
    3 4 5 6 7
    3 4 5 6 7 8
    3 4 5 6 7 8
    
    
    
    
    4
    4 5
    4 5 6
    4 5 6 7
    4 5 6 7 8
    4 5 6 7 8 9
    9
    

    发现决策转移点k的确具有单调性,那么表示dp式子也具有决策单调性,但是由于本人太菜,什么都不会推,所以我们直接来试一下哪种范围是正确的
    //范围无外乎有两种:
    s[i+1][j]<=s[i][j]<=s[i][j-1]
    s[i][j-1]<=s[i][j]<=s[i+1][j]

    发现符合第二个式子(也就是说用第二个式子可以推出正确答案)

    至此,即使我们不会四边形不等式,这道题依旧完美AC~~

  • 相关阅读:
    第一阶段意见评论
    软件工程--第十一周学习进度
    第一阶段SCRUM冲刺 10
    冲刺(三)
    冲刺(二)
    冲刺(一)
    梦断代码阅读笔记01
    第八周总结
    NABCD项目分析
    第七周总结
  • 原文地址:https://www.cnblogs.com/yxr001002/p/14544506.html
Copyright © 2011-2022 走看看