51nod oj 1021 石子歸併【區間dp】
阿新 • • 發佈:2019-02-08
題目連結:1021
每次只能合併相連的石堆-.-我們可以建一個dp
dp [ i ] [ k ] 表示從i號一共K個石頭合併再一起所花費的代價-.-
轉換方程1:dp[ i ] [ k ]=min( dp [ i ] [ k ] ,dp[ i ] [ j ] +dp [i+k ] [ k-j] +he[ i ] [ k ]); j代表合併時第一個的長度--he[ i ] [ k ] 代表從i開始k個石頭的代價和
轉換方程1:dp[ i ] [ k ]=min( dp [ i ] [ k ] ,dp[ i ] [ j-i ] +dp [ j ] [ k-j+i] +he[ i ] [ k ] ); j代表合併時後一個的開頭--he[ i ] [ k ] 代表從i開始k個石頭的代價和
程式碼1:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int dp[120][120],he[120][120],shu[120]; int main() { int n;scanf("%d",&n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) dp[i][j]=999999999; memset(he,0,sizeof(he)); for (int i=1;i<=n;i++) { scanf("%d",&shu[i]); dp[i][1]=0; } for (int k=2;k<=n;k++) for (int i=1;i+k-1<=n;i++) for (int j=i;j<i+k;j++) he[i][k]+=shu[j]; for (int k=2;k<=n;k++) for (int i=1;i+k-1<=n;i++) for (int j=1;j<k;j++) dp[i][k]=min(dp[i][k],(dp[i][j]+dp[i+j][k-j])+he[i][k]); printf("%d\n",dp[1][n]); return 0; }
程式碼2:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int dp[120][120],he[120][120],shu[120]; int main() { int n;scanf("%d",&n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) dp[i][j]=999999999; memset(he,0,sizeof(he)); for (int i=1;i<=n;i++) { scanf("%d",&shu[i]); dp[i][1]=0; } for (int k=2;k<=n;k++) for (int i=1;i+k-1<=n;i++) for (int j=i;j<i+k;j++) he[i][k]+=shu[j]; for (int k=2;k<=n;k++) for (int i=1;i+k-1<=n;i++) for (int j=i+1;j<i+k;j++) dp[i][k]=min(dp[i][k],(dp[i][j-i]+dp[j][k-j+i])+he[i][k]); printf("%d\n",dp[1][n]); return 0; }