石子合并问题--直线版 HRBUST - 1818
注释的部分是平行四边形优化,下面是分析的草稿
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 300;
int sum[N],n;
int Minval()
{
int dp[N][N];memset(dp,INF,sizeof(dp));
for(int i=1;i<=n;++i) dp[i][i]=0;
for(int len=1;len<n;++len)
for(int i=1;i<=n-len;++i)
{
int j=i+len;
for(int k=i;k<j;k++)
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
}
printf("%d ",dp[1][n]);
return dp[1][n];
}
int Maxval()
{
int dp[N][N]; memset(dp,0,sizeof(dp));
for(int i=1;i<=n;++i) dp[i][i]=0;
for(int len=1;len<n;++len)
for(int i=1;i<=n-len;++i)
{
int j=i+len;
for(int k=i;k<j;k++)
// dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum[j]-sum[i];同时扩大再取小,对结果没影响
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
}
printf("%d
",dp[1][n]);
return dp[1][n];
}
int main()
{
while(cin>>n)
{
sum[0]=0;
for(int i=1;i<=n;++i)
{
int x;
cin>>x;
sum[i]=sum[i-1]+x;//sum[i]代表 1-i所有数字的和
}
Minval();
Maxval();
}
return 0;
}
//int Minval()
//{
// int dp[N][N];
// for(int i=1;i<=n;++i) { dp[i][i]=0; s[i][i]=i; }
// for(int len=1;len<n;++len)
// for(int i=1;i<=n-len;++i)
// {
// int j=i+len;
// dp[i][j]=INF;
// for(int k=s[i][j-1];k<=s[i+1][j];k++)
// // dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum[j]-sum[i];同时扩大再取小,对结果没影响
// if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])
// {
// dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
// s[i][j]=k;
// }
// }
// return dp[1][n];
//}
B - Cheapest Palindrome[回文串]
#include<iostream>
using namespace std;
int w[30],n,m,dp[2005][2005];
char s[2005],ch;
int main()
{
int x,y;
while(cin>>n>>m)
{
cin>>s;
for(int i=0;i<n;++i)
{
cin>>ch>>x>>y;
w[ch-'a']=min(x,y);
}
for(int i=m-1;i>=0;i--)
{
for(int j=i+1;j<m;++j)
{
if(s[i]==s[j])
{
dp[i][j]=dp[i+1][j-1];
}
else
{
dp[i][j]=min(dp[i+1][j]+w[s[i]-'a'],dp[i][j-1]+w[s[j]-'a']);
}
}
}
cout<<dp[0][m-1]<<endl;
}
return 0;
}
C - Monkey Party[平行四边形]
#include<iostream> #include<cstring> #include<stdio.h> #define INF 0x3f3f3f3f using namespace std; const int N = 1e4; int n,m; int dp[N][N],sum[N],w[N]; int main() { while(cin>>m) { for(int i=1;i<=m;++i) { cin>>w[i]; sum[i]=sum[i-1]+w[i]; } n=m*2; for(int i=m+1,j=1;i<=n;++i,++j) { // cout<<sum[i]<<","<<w[j]<<endl; sum[i]=sum[i-1]+w[j]; } memset(dp,INF,sizeof(dp)); for(int i=1;i<=n;++i) dp[i][i]=0; for(int len=1;len<n;++len) for(int i=1;i<=n-len;++i) { int j=i+len; for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); } printf("%d",dp[1][m]); } return 0; }
#include<iostream>
#include<cstring>
#include<stdio.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 2e3 + 10;
int n,m;
int dp[N][N],sum[N],p[N][N],w[N];
int main()
{
while(cin>>m)
{
for(int i=1;i<=m;++i)
{
cin>>w[i];
sum[i]=sum[i-1]+w[i];
}
n=m*2;
for(int i=m+1,j=1;i<=n;++i,++j)
{
sum[i]=sum[i-1]+w[j];
}
memset(dp,0,sizeof(dp));
memset(p,0,sizeof(p));
for(int i=1;i<=n;++i) { dp[i][i]=0;p[i][i]=i; }
for(int len=1;len<n;++len)
for(int i=1;i<=n-len;++i)
{
int j=i+len;dp[i][j]=INF;
for(int k=p[i][j-1];k<=p[i+1][j];k++)
if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])
{
dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
p[i][j]=k;
}
}
int res = INF;
for (int i = 1; i <= m; i++) {
res = min(res,dp[i][i + m - 1]);
}
printf("%d
",res);
}
return 0;
}
