• 四边形不等式求解合并石子(菜鸡做法)


    这里暂时先只提供min的做法,求max的时候直接把值改成负数即可
    dp:
    f[i][j]=f[i][k]+f[k+1][j]+d[j]-d[i-1];

    正常代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 402
    
    using namespace std;
    
    ll n,a[maxn];
    ll f[maxn][maxn];
    ll d[maxn];
    
    
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i];
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=2*n;i++)
    	{
    		d[i]=d[i-1]+a[i];
    		f[i][i]=0;
    	
    	}
    	
    	
    	
    	
    	for(int l=2;l<=n;l++){
    		for(int i=1;i<=2*n-l+1;i++){
    			int j=i+l-1;
    			for(int k=i;k<j;k++){
    //				cout<<f[i][]
    				if(f[i][j]>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					cout<<k<<" ";
    					f[i][j]=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    //					cout<<"jnvadl
    ";
    				}
    				
    			}cout<<'
    ';
    			
    		}
    	}
    	
    	ll ans=99999999;
    	for(int i=1;i<=n;i++){
    		ans=min(ans,f[i][i+n-1]);
    	}
    	
    	cout<<ans<<'
    ';
    	return 0;
    }
    

    如果想用四边形不等式来做,那么我们先判断这个式子是不是符合四边形不等式的条件,发现和模板长得好像差不多~~

    我们接着枚举断点k,看一看是不是有单调性:

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 402
    
    using namespace std;
    
    ll n,a[maxn];
    ll f[maxn][maxn];
    ll d[maxn];
    
    
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i];
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=2*n;i++)
    	{
    		d[i]=d[i-1]+a[i];
    		f[i][i]=0;
    	
    	}
    	
    	
    	
    	
    	for(int l=2;l<=n;l++){
    		for(int i=1;i<=2*n-l+1;i++){
    			int j=i+l-1;
    			for(int k=i;k<j;k++){
    //				cout<<f[i][]
    				if(f[i][j]>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					cout<<k<<" ";
    					f[i][j]=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    //					cout<<"jnvadl
    ";
    				}
    				
    			}cout<<'
    ';
    			
    		}
    	}
    	
    	ll ans=99999999;
    	for(int i=1;i<=n;i++){
    		ans=min(ans,f[i][i+n-1]);
    	}
    	
    	cout<<ans<<'
    ';
    	return 0;
    }
    

    结果:

    4
    4 5 9 4
    1
    2
    3
    4
    5
    6
    7
    1 2
    2
    3
    4 5
    5 6
    6
    1 2
    2 3
    3
    4 5 6
    5 6
    43
    

    发现的确是有单调性的,所以我们的dp也有很大可能具有单调性

    两个都试一下:
    第一个;
    f[i+1][j]<=s[i][j]<=f[i][j-1]
    i正序枚举:

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 402
    
    using namespace std;
    
    ll n,a[maxn];
    ll f[maxn][maxn];
    ll d[maxn],s[maxn][maxn];
    
    
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i],s[i][i]=i,s[i+n][i+n]=i+n;
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=2*n;i++)
    	{
    		d[i]=d[i-1]+a[i];
    		f[i][i]=0;
    	
    	}
    	
    	
    	
    	
    	/*for(int l=2;l<=n;l++){
    		for(int i=1;i<=2*n-l+1;i++){
    			int j=i+l-1;
    			for(int k=i;k<j;k++){
    //				cout<<f[i][]
    				if(f[i][j]>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					cout<<k<<" ";
    					f[i][j]=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    //					cout<<"jnvadl
    ";
    				}
    				
    			}cout<<'
    ';
    			
    		}
    	}*/
    	
    	for(int i=1;i<=2*n;i++) 
    		for(int j=i+1;j<=2*n;j++){
    			ll tmp=0x3f3f3f3f3f,p;
    			for(int k=s[i+1][j];k<=s[i][j-1];k++){
    				if(tmp>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					tmp=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    					p=k;
    				}
    			}
    			f[i][j]=tmp;
    			s[i][j]=p;//决策点 
    		}
    	
    	
    	ll ans=99999999;
    	for(int i=1;i<=n;i++){
    		ans=min(ans,f[i][i+n-1]);
    	}
    	
    	cout<<ans<<'
    ';
    	return 0;
    }
    

    结果错误~~

    i倒序枚举;

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 402
    
    using namespace std;
    
    ll n,a[maxn];
    ll f[maxn][maxn];
    ll d[maxn],s[maxn][maxn];
    
    
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i],s[i][i]=i,s[i+n][i+n]=i+n;
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=2*n;i++)
    	{
    		d[i]=d[i-1]+a[i];
    		f[i][i]=0;
    	
    	}
    	
    	
    	
    	
    	/*for(int l=2;l<=n;l++){
    		for(int i=1;i<=2*n-l+1;i++){
    			int j=i+l-1;
    			for(int k=i;k<j;k++){
    //				cout<<f[i][]
    				if(f[i][j]>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					cout<<k<<" ";
    					f[i][j]=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    //					cout<<"jnvadl
    ";
    				}
    				
    			}cout<<'
    ';
    			
    		}
    	}*/
    	
    	for(int i=n*2;i>=1;i--)//倒叙 
    		for(int j=i+1;j<=2*n;j++){
    			ll tmp=0x3f3f3f3f3f,p;
    			for(int k=s[i+1][j];k<=s[i][j-1];k++){
    				if(tmp>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					tmp=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    					p=k;
    				}
    			}
    			f[i][j]=tmp;
    			s[i][j]=p;//决策点 
    		}
    	
    	
    	ll ans=99999999;
    	for(int i=1;i<=n;i++){
    		ans=min(ans,f[i][i+n-1]);
    	}
    	
    	cout<<ans<<'
    ';
    	return 0;
    }
    
    

    结果错误~~

    试一试第二种:
    s[i][j-1]<=s[i][j]<=s[i+1][j]

    i正序:

    
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 402
    
    using namespace std;
    
    ll n,a[maxn];
    ll f[maxn][maxn];
    ll d[maxn],s[maxn][maxn];
    
    
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i],s[i][i]=i,s[i+n][i+n]=i+n;
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=2*n;i++)
    	{
    		d[i]=d[i-1]+a[i];
    		f[i][i]=0;
    	
    	}
    	
    	
    	
    	
    	/*for(int l=2;l<=n;l++){
    		for(int i=1;i<=2*n-l+1;i++){
    			int j=i+l-1;
    			for(int k=i;k<j;k++){
    //				cout<<f[i][]
    				if(f[i][j]>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					cout<<k<<" ";
    					f[i][j]=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    //					cout<<"jnvadl
    ";
    				}
    				
    			}cout<<'
    ';
    			
    		}
    	}*/
    	
    	for(int i=1;i<=2*n;i++)
    		for(int j=i+1;j<=2*n;j++){
    			ll tmp=0x3f3f3f3f3f,p;
    			for(int k=s[i][j-1];k<=s[i+1][j];k++){
    				if(tmp>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					tmp=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    					p=k;
    				}
    			}
    			f[i][j]=tmp;
    			s[i][j]=p;//决策点 
    		}
    	
    	
    	ll ans=99999999;
    	for(int i=1;i<=n;i++){
    		ans=min(ans,f[i][i+n-1]);
    	}
    	
    	cout<<ans<<'
    ';
    	return 0;
    }
    
    

    结果错误

    倒序:

    
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 402
    
    using namespace std;
    
    ll n,a[maxn];
    ll f[maxn][maxn];
    ll d[maxn],s[maxn][maxn];
    
    
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i],s[i][i]=i,s[i+n][i+n]=i+n;
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=2*n;i++)
    	{
    		d[i]=d[i-1]+a[i];
    		f[i][i]=0;
    	
    	}
    	
    	
    	
    	
    	/*for(int l=2;l<=n;l++){
    		for(int i=1;i<=2*n-l+1;i++){
    			int j=i+l-1;
    			for(int k=i;k<j;k++){
    //				cout<<f[i][]
    				if(f[i][j]>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					cout<<k<<" ";
    					f[i][j]=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    //					cout<<"jnvadl
    ";
    				}
    				
    			}cout<<'
    ';
    			
    		}
    	}*/
    	
    	for(int i=n*2;i>=1;i--)//倒叙 
    		for(int j=i+1;j<=2*n;j++){
    			ll tmp=0x3f3f3f3f3f,p;
    			for(int k=s[i][j-1];k<=s[i+1][j];k++){
    				if(tmp>f[i][k]+f[k+1][j]+d[j]-d[i-1]){
    					tmp=f[i][k]+f[k+1][j]+d[j]-d[i-1];
    					p=k;
    				}
    			}
    			f[i][j]=tmp;
    			s[i][j]=p;//决策点 
    		}
    	
    	
    	ll ans=99999999;
    	for(int i=1;i<=n;i++){
    		ans=min(ans,f[i][i+n-1]);
    	}
    	
    	cout<<ans<<'
    ';
    	return 0;
    }
    

    结果正确!!

    综上:四边形不等式很简单,多试几次就好啦~~()

  • 相关阅读:
    BUUCTF [XMAN2018排位赛]四道misc题汇总
    祥云杯2020 Misc题解
    win10更换pip源
    BUUCTF N1BOOK配套题目
    kali下docker安装教程
    湖湘杯2020 Misc题解
    7号夺宝1元购iPhone6s 1元众筹怎么玩
    html5 的服务器推送 Server-sent Events和 websocket这两个是不是同一个东西,是两个不同的?
    WebSocket 是什么原理?为什么可以实现持久连接?
    使用HTML5的十大原因
  • 原文地址:https://www.cnblogs.com/yxr001002/p/14544782.html
Copyright © 2020-2023  润新知