题意:有一根长度为L的木棍,和n个切割点的位置(按照从小到大排序),你的任务是在这些切割点的位置把棍子切成n+1份,使得总切割费用最小。每次切割的费用等于被切的木棍长度
思路:这道题与最优矩阵连乘的思想一样,那就是分析最优子结构,再根据子结构来定义状态,首先我们假定第一次分割的最优方案是在k处分割,得到0~k与k~L两段木棍,那么如何最优分割0~k与0~L就是它的子问题,我们根据子问题定义状态d(i,j)是分割从割点i到割点j的最优方案,状态转移方程 d(i,j)=min{d(i,k)+d(k,j)+(cut[j]-cut[i])}(其中i<k<j),接下来是确定边界,d(i,i)=0 和 d(i,i+1)=0,并注意赋初值INF
代码:
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #define INF 0x3f3f3f3f using namespace std; int d[55][55]; int cut[55]; bool visit[55][55]; int L,n; int dp(int i,int j) { if((j-i)<=1) return 0; if(visit[i][j]==true) return d[i][j]; visit[i][j]=true; for(int k=i+1;k<j;k++) d[i][j]=min(d[i][j],dp(i,k)+dp(k,j)+(cut[j]-cut[i])); return d[i][j]; } int main(int argc, char const *argv[]) { while(cin>>L&&L) { cin>>n; for(int i=1;i<=n;i++) { scanf("%d",&cut[i]); } cut[0]=0; cut[n+1]=L; memset(visit,false,sizeof(visit)); memset(d,INF,sizeof(d)); int ans=dp(0,n+1); cout<<"The minimum cutting is "<<ans<<"."<<endl; } return 0; }