[NOI1995] stones merge solution to a problem

A classic dp title

Playground around a circular stones piled placed N, Stone is to have order to merge into a pile. Each time only a predetermined selected adjacent stack 2 into a new pile and the new pile of stones number, remember that the combined score.

Test design an algorithm to calculate the N stones piled into a stack the minimum combined score and maximum score.

We look at this question of simple version

There are N stones piled in a row, each with a certain number of stones piled. Now we want to pile stones and N into a pile. The combined process only each adjacent piles of stones in a pile, the cost of each merger takes for these piles of stones and, after N-1 times the combined into a pile. Find the total cost of the minimum.

This question is not cyclic, we can directly solve dp, I set a start is f [i] [j] table is to merge ij minimum cost within this range, so with the state transition equation

f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]) (i<=k<=j)

I wrote the following code

#include<bits/stdc++.h>
using namespace std;
int n,f[110][110],a[110];
int s[110];
int main(){
   scanf("%d",&n);
   memset(f,0x3f,sizeof(f));
   for(int i=1;i<=n;++i){
       scanf("%d",&a[i]);
       f[i][i]=0;
       s[i]=s[i-1]+a[i];
   }
   for(int i=1;i<=n;++i){
       for(int j=i;j<=n;++j){
           for(int k=i;k<=j;++k){
               f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
           }
       }
   }
   printf("%d",f[1][n]);
   return 0;
} 

However, goose answer wrong, and why?

With the help of the chiefs of the room I see

Because demand is to use a large range of values ​​between cells, but the starting point is fixed above the program has been running back will lead to update some point too late, when they use less than, so I wrote the following code

#include<bits/stdc++.h>
using namespace std;
int n,f[110][110],a[110],T=10;
int s[110];
int main(){
    scanf("%d",&n);
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        f[i][i]=0;
        s[i]=s[i-1]+a[i];
    }
    while(T--){
        for(int i=1;i<=n;++i){
            for(int j=i;j<=n;++j){
                for(int k=i;k<=j;++k){
                    f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
                }
            }
        }
    }
    printf("%d",f[1][n]);
    return 0;
} 

Since not run again answer, that much I do not like to run a few times,Gangster same room are shockedAlthough the answer is right, but not the positive solution, positive solution should enumerate length on the outside, and then enumerate the starting point to calculate the end dp

Code

#include<bits/stdc++.h>
using namespace std;
int n,f[110][110],a[110],T=10;
int s[110];
int main(){
    scanf("%d",&n);
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        f[i][i]=0;
        s[i]=s[i-1]+a[i];
    }
    for(int L=2;L<=n;++L){
        for(int i=1;i<=n;++i){
            int j=i+L-1;
            for(int k=i;k<=j;++k){
                f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
            }
        }
    }
    printf("%d",f[1][n]);
    return 0;
} 

Back noi1995 this question, we can see that ring directly to redouble off the ring chain (routine), similar ideas with the rest of the above

#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,f[410][410],g[410][410],a[410];
int s[410],maxn,minn=1<<30;
int main(){
    scanf("%d",&n);
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        f[i][i]=0;
        s[i]=s[i-1]+a[i];
    }
    for(int i=1;i<=n;++i){
        s[i+n]=s[i+n-1]+a[i];
        f[i+n][i+n]=0;//这个初始化一定要记得
    }
    for(int L=2;L<=n;++L){
        for(int i=1;i<=n+n;++i){//起点可以枚举到2n
            int j=i+L-1;
            if(j>n*2) break;//不符合
            for(int k=i;k<j;++k){
                f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
                g[i][j]=max(g[i][j],g[i][k]+g[k+1][j]+s[j]-s[i-1]);
            }
        }
    }
    for(int i=1;i<=n;++i){
        maxn=max(maxn,g[i][i+n-1]);
        minn=min(minn,f[i][i+n-1]);
    }
    printf("%d\n%d\n",minn,maxn);
    return 0;
} 

Guess you like

Origin www.cnblogs.com/donkey2603089141/p/11414990.html