看了下感觉区间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;
}