将一条长度为x的线段切成若干段,切割点已给出,每次切割的成本为切割后产生的两段线段长度之和,求最小的切割成本。
20,[2,5,10,18]
45
线段长为20,切割点为[2,5,10,18]。
第一种方案:
1.先切开第一个点,成本为2+18=20
2.切开第二个点,成本为3+15=18
3.切开第三个点,成本为5+10=15
4.切开第四个点,成本为8+2=10
总成本为:20 + 18 + 15 + 10 = 63;
第二种方案:
1.先切开第一个点,成本为5+15=20
2.切开第二个点,成本为2+3=5
3.切开第三个点,成本为5+10=15
4.切开第四个点,成本为8+2=10
总成本为:20 + 5 + 15 + 10 = 50;
切割点个数<300x<1000000
public int attackMonster (int monsterLength, int[] monsterPoint) { // write code here // 直接动态规划 // 用 dp[i][j] 表示 monsterPoint(i...j)之间的切割点的最小成本 ,这里是开区间 // base case dp[i][i] = monsterLength; // 状态转移 // dp[i][j] = dp[i][k] + dp[k][j] + (以k为切割点,i j 为边界的成本) Arrays.sort(monsterPoint); int n = monsterPoint.length; int [] scale = new int[n+2]; // 添加 0 和 monsterLength 切割点 scale[0]=0; scale[n+1] = monsterLength; for(int i=1;i<=n;++i){ scale[i]=monsterPoint[i-1]; } int [][] dp = new int[n+2][n+2]; //base case for(int i=0;i<=n+1;++i){ dp[i][i] = monsterLength; } // status change for(int i=n;i>=0;--i){ for(int j=i+1;j<=n+1;++j){ if (j-i==1){dp[i][j]=0;} else{ dp[i][j] = Integer.MAX_VALUE; for(int k=i+1;k<j;++k){ int spice = dp[i][k] + dp[k][j] + (scale[k]-scale[i]) + (scale[j]-scale[k]); dp[i][j] = Math.min(spice,dp[i][j]); } } } } return dp[0][n+1]; }