1. 程式人生 > >Uva 10003 Cutting Sticks (類似於最優矩陣連乘的dp)

Uva 10003 Cutting Sticks (類似於最優矩陣連乘的dp)

out min 分析 sin [] can 任務 cin algo

題意:有一根長度為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)