SDNU1045(1048)石子合并(动态规划问题)

参考大佬博客:https://blog.csdn.net/sunshine_yg/article/details/47209299

代码1045:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e2+10;
const int inf=0x3f3f3f3f;
int dp[maxn][maxn];
int num[maxn];
int sum[maxn];
int n;
void solve()
{
    int k,ans;
    for(int i=1; i<=n; ++i)
        for(int j=1; i+j<=n; ++j)
        {
            k=i+j;
            ans=sum[k]-sum[j-1];
            dp[j][k]=inf;
            for(int t=j; t<k; ++t)
                dp[j][k]=min(dp[j][k],dp[j][t]+dp[t+1][k]+ans);
        }
}
int main()
{
    memset(dp,0,sizeof(dp));
    memset(sum,0,sizeof(sum));
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
    {
        scanf("%d",&num[i]);
        sum[i]=sum[i-1]+num[i];
    }
    solve();
    printf("%d\n",dp[1][n]);
    return 0;
}

代码1048:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e2+10;
const int inf=0x3f3f3f3f;
int dp[maxn][maxn];
int num[maxn];
int sum[maxn];
int n;
int gsum(int b,int e)
{
    if(e<=n)
        return sum[e]-sum[b-1];
    return sum[e%n]+sum[n]-sum[b-1];
}
int solve()
{
    int k,ans;
    //printf("测试点1\n");
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
        {
            //printf("%d %d\n",i,j);
            k=(i+j)%n==0?n:(i+j)%n;
            ans=gsum(j,j+i);
            dp[j][k]=inf;
            for(int t=j; t<j+i; ++t)
            {
                dp[j][k]=min(dp[j][k],dp[j][t % n == 0 ? n : t % n]+dp[(t + 1) % n == 0 ? n : (t + 1) % n][k]+ans);
            }
        }
    //printf("测试点2\n");
    ans=dp[1][n];
    for(int i=2; i<=n; ++i)
        if(ans>dp[i][i-1])
            ans=dp[i][i-1];
    return ans;
}
int main()
{
    memset(dp,0,sizeof(dp));
    memset(sum,0,sizeof(sum));
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
    {
        scanf("%d",&num[i]);
        sum[i]=sum[i-1]+num[i];
    }
    int res=solve();
    printf("%d\n",res);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_41658955/article/details/86938477
今日推荐