UVa 10003 - Cutting Sticks(区间dp)
题目:有一个长l的木头,切成n+1段,切割的代价是当前段长度,求最小代价和。
分析:dp,区间动态规划。石子合并的逆过程。
状态:设F(i,j)为从点i切到j长度的木头切割成对应的小段代价,则有转移方程:
F(i,j)= min(F(i,k)+F(k,j)+cost(i,j)) {其中 i < k < j };
这里注意,dp过程按区间大小递增顺序进行。
说明:注意边界条件,只有一小段时代价为0。
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define pll pair<ll,ll>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rep1(i,a,b) for(int i=a;i>=b;i--)
#define rson rt<<1|1,m+1,r
#define lson rt<<1,l,m
using namespace std;
const int N=100;
int cut[N];
int dp[N][N];
int main()
{
int l,n;
while (cin>>l>>n)
{
for (int i=1;i<=n;++i)
cin>>cut[i];
cut[0]=0; cut[n+1]=l;
for (int i=0;i<55;++i)
for (int j=0;j<55;++j)
dp[i][j]=1000000;
for (int i=0;i<= n;++i)
dp[i][i+1]=0;
for (int d=2;d<=n+1;++d)//d为长度,s+d为终点,保证其中至少有一个点可以被选到
for (int s=0;s+d<=n+1;++s)//s为起始点
for (int k=s+1;k<s+d;++k)//不选起点和终点
if (dp[s][s+d]>dp[s][k]+dp[k][s+d]+cut[s+d]-cut[s])
dp[s][s+d]=dp[s][k]+dp[k][s+d]+cut[s+d]-cut[s];
cout<<"The minimum cutting is "<<dp[0][n+1]<< "." <<endl;
}
return 0;
}