石子合并

来源:互联网 发布:知乎怎么打不开 编辑:程序博客网 时间:2024/04/29 23:19

在一个圆形操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。

#include <stdio.h>#define N 100#define INF 65536 #define min(a,b) a<b?a:b#define max(a,b) a>b?a:bint MAX,MIN,a[N],n;int dp[N][N][2];//0代表最小值,1代表最大值int total(int i, int j){int total=0;for(int k=i;k<=j;k++)total += a[k];return total;}void function(){int i,j,k,len;for(i=1;i<=n;i++)dp[i][i][0] = dp[i][i][1] = 0;for(len=2;len<=n;len++)//有几堆合并for(i=1;i<=n-len+1;i++)//从第几堆开始{j=i+len-1;//到第几堆dp[i][j][0] = INF;dp[i][j][1] = -INF;for(k=i;k<j;k++){if(dp[i][k][0]+dp[k+1][j][0]+total(i,j) < dp[i][j][0])dp[i][j][0]=dp[i][k][0]+dp[k+1][j][0]+total(i,j);if(dp[i][k][1]+dp[k+1][j][1]+total(i,j) > dp[i][j][1])dp[i][j][1]=dp[i][k][1]+dp[k+1][j][1]+total(i,j);}}MAX = max(MAX,dp[1][n][1]);MIN = min(MIN,dp[1][n][0]);}int main(){int i;MAX = -INF, MIN = INF;printf("输入堆的个数:");scanf("%d",&n);printf("输入每堆石子个数:");for(i=1;i<=n;i++)scanf("%d",&a[i]);function();for(i=2;i<=n;i++)//圆圈拆成一根根的直线{int last = a[1];for(int j=2;j<=n;j++)a[j-1] = a[j];a[n] = last;function();}printf("最大值为:%d\n",MAX);printf("最小值为:%d\n",MIN);return 0;}



还有一种空间换时间方法,圆圈用两倍直线代替,比如圆圈长度为N,则用2N的数组表示

#include <stdio.h>#define N 100#define INF 65536 #define min(a,b) a<b?a:b#define max(a,b) a>b?a:bint MAX,MIN,a[N],n;int dp[N][N][2];//0代表最小值,1代表最大值int total(int i, int j){int total=0;for(int k=i;k<=j;k++)total += a[k];return total;}void function(){int i,j,k,len;for(i=1;i<=2*n;i++)dp[i][i][0] = dp[i][i][1] = 0;for(len=2;len<=n;len++)//有几堆合并for(i=1;i<=2*n-len+1;i++)//从第几堆开始{j=i+len-1;//到第几堆dp[i][j][0] = INF;dp[i][j][1] = -INF;for(k=i;k<j;k++){if(dp[i][k][0]+dp[k+1][j][0]+total(i,j) < dp[i][j][0])dp[i][j][0]=dp[i][k][0]+dp[k+1][j][0]+total(i,j);if(dp[i][k][1]+dp[k+1][j][1]+total(i,j) > dp[i][j][1])dp[i][j][1]=dp[i][k][1]+dp[k+1][j][1]+total(i,j);}}for(i=1;i<=n;i++){if(dp[i][i+n-1][0] < MIN)MIN = dp[i][i+n-1][0];if(dp[i][i+n-1][1] > MAX)MAX = dp[i][i+n-1][1];}}int main(){int i;MAX = -INF, MIN = INF;printf("输入堆的个数:");scanf("%d",&n);printf("输入每堆石子个数:");for(i=1;i<=n;i++)scanf("%d",&a[i]);for(i=n+1;i<=2*n;i++)//这里不同a[i] = a[i-n];function();printf("最大值为:%d\n",MAX);printf("最小值为:%d\n",MIN);return 0;}


原创粉丝点击