首页 > 代码库 > Uva 10003 Cutting Sticks (类似于最优矩阵连乘的dp)

Uva 10003 Cutting Sticks (类似于最优矩阵连乘的dp)

题意:有一根长度为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;
}

 

Uva 10003 Cutting Sticks (类似于最优矩阵连乘的dp)