看了下感覺區間dp就是一種套路,直接上的板子代碼就好了。
基礎題ac代碼:石子歸並
#include<bits/stdc++.h>
using namespace std; typedef long long ll; typedef unsigned long long ull; int dir[8][2]={{1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1},{0,-1},{-1,0}}; #define pi acos(-1)
#define ls rt<<1
#define rs rt<<1|1
#define me0(s) memset(s,0,sizeof(s))
#define me1(s) memset(s,1,sizeof(s))
#define mef(s) memset(s,-1,sizeof(s))
#define meinf(s) memset(s,inf,sizeof(s))
#define inf 0x3f3f3f
const int N=1e6+6; inline int read() { char c=getchar(); int x=0, f=1; while(c<'0'|c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; } ll exgcd(ll a,ll b){ if(b==0) return a; exgcd(b,a%b); } ll q_pow(ll a,ll b,ll mod){ ll anss=1; while(b){ if(b&1) anss=anss*a%mod; a=a*a%mod; b>>=1; } return anss; } ll q_mul(ll a,ll b,ll mod){ ll anss=0; while(b){ if(b&1) anss=(anss+a)%mod; a=(a+a)%mod; b>>=1; } return anss; } int dp[105][105]; int sum[105]; int stone[105]; int main(int argc, char * argv[]){ ios::sync_with_stdio(false); int n; cin>>n; me0(sum); meinf(dp); for(int i=1;i<=n;i++){ cin>>stone[i]; sum[i]=sum[i-1]+stone[i]; dp[i][i]=0; } for(int len=1;len<=n;len++){//枚舉長度
for(int j=1;j+len<=n+1;j++){//枚舉起點,ends<=n
int ends=j+len-1; for(int i=j;i<ends;i++){//枚舉分割點,更新小區間最優解
dp[j][ends]=min(dp[j][ends],dp[j][i]+dp[i+1][ends]+sum[ends]-sum[j-1]); } } } cout<<dp[1][n]<<endl; return 0; }
但是這樣一眼就看出來了復雜度是n3的復雜度,這個復雜度數據稍稍大點就爆了,所以還是要用到四邊形不等式優化。
但是由於個人感覺很復雜,看了不是很懂,直接貼個鏈接:四邊形不等式優化。
優化過的AC的代碼:
#include<bits/stdc++.h>
using namespace std; typedef long long ll; typedef unsigned long long ull; int dir[8][2]={{1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1},{0,-1},{-1,0}}; #define pi acos(-1)
#define ls rt<<1
#define rs rt<<1|1
#define me0(s) memset(s,0,sizeof(s))
#define me1(s) memset(s,1,sizeof(s))
#define mef(s) memset(s,-1,sizeof(s))
#define meinf(s) memset(s,inf,sizeof(s))
#define inf 0x3f3f3f
const int N=1e6+6; inline int read() { char c=getchar(); int x=0, f=1; while(c<'0'|c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; } ll exgcd(ll a,ll b){ if(b==0) return a; exgcd(b,a%b); } ll q_pow(ll a,ll b,ll mod){ ll anss=1; while(b){ if(b&1) anss=anss*a%mod; a=a*a%mod; b>>=1; } return anss; } ll q_mul(ll a,ll b,ll mod){ ll anss=0; while(b){ if(b&1) anss=(anss+a)%mod; a=(a+a)%mod; b>>=1; } return anss; } int dp[105][105]; int sum[105]; int stone[105]; int main(int argc, char * argv[]){ ios::sync_with_stdio(false); int n; cin>>n; me0(sum); meinf(dp); int s[111][111]; for(int i=1;i<=n;i++){ cin>>stone[i]; sum[i]=sum[i-1]+stone[i]; dp[i][i]=0; s[i][i]=i; } for(int len=1;len<=n;len++){//枚舉長度
for(int j=1;j+len<=n+1;j++){//枚舉起點,ends<=n
int ends=j+len-1; for(int k=s[j][ends-1];k<=s[j+1][ends];k++){ if(dp[j][ends]>dp[j][k]+dp[k+1][ends]+sum[ends]-sum[j-1]){ dp[j][ends]=dp[j][k]+dp[k+1][ends]+sum[ends]-sum[j-1]; s[j][ends]=k; } } } } cout<<dp[1][n]<<endl; return 0; }