Click Here
题意:任意选取一个数,并与左右相邻的数相乘,求最大和
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int main()
{
int a[220],dp[220][220];
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int p=2;p<n;p++)
{
for(int i=1;i+p<=n;i++)
{
int j=i+p;
dp[i][j]=inf;
for(int k=i+1;k<j;k++)
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j]);
}
}
printf("%d\n",dp[1][n]);
return 0;
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int dpma[110][110],dpmi[110][110];
int a[110],sum[110];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(sum,0,sizeof sum);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]),dpma[i][i]=dpmi[i][i]=0;
for(int i=1;i<=n;++i)
sum[i]=sum[i-1]+a[i],dpma[i][i]=0;
for(int j=2;j<=n;++j)
{
for(int i=1;j+i-1<=n;++i)
{
int p=i+j-1,tmp=sum[p]-sum[i-1];
dpma[i][p]=-inf;
dpmi[i][p]=inf;
for(int k=i;k<p;k++)
{
dpma[i][p]=max(dpma[i][p],dpma[i][k]+dpma[k+1][p]+tmp);
dpmi[i][p]=min(dpmi[i][p],dpmi[i][k]+dpmi[k+1][p]+tmp);
}
}
}
printf("%d %d\n",dpmi[1][n],dpma[1][n]);
}
return 0;
}
石子合并
范围太大,用上面的方法肯定就不行了,引入新方法GarsiaWachs
如果a[i-1]<a[i+1]则合并a[i-1]和a[i]为ans,并向前搜索放到原数组中第一个大于等于ans的位置后面,循环往复
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=5e4+10;
typedef long long ll;
int a[maxn],t;
ll ans;
void dfs(int k)
{
int tmp=a[k-1]+a[k];//合并
ans+=tmp;
for(int i=k;i<t-1;++i)//向前找到不满足大于ans的位置
a[i]=a[i+1];
t--;
int j;
for(j=k-1;j>0&&a[j-1]<tmp;--j)//向前更新
a[j]=a[j-1];
a[j]=tmp;
while(j>=2&&a[j]>=a[j-2])
{
int d=t-j;
dfs(j-1);
j=t-d;
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d",&a[i]);
t=1;
ans=0;
for(int i=1;i<n;++i)
{
a[t++]=a[i];
while(t>=3&&a[t-3]<=a[t-1])
dfs(t-2);
}
while(t>1)
dfs(t-1);
printf("%lld\n",ans);
return 0;
}