当前位置: 代码迷 >> 综合 >> UVA - 10003 Cutting Sticks - (DP)
  详细解决方案

UVA - 10003 Cutting Sticks - (DP)

热度:94   发布时间:2024-01-12 15:16:25.0

题目链接:https://cn.vjudge.net/problem/UVA-10003

题意:给出一根长为L的木棍,给出长为n的c数组,c[i]代表在木棍的长为c[i]处为一个切割点,每次切割的木棍的长度为花费,让选择切点的顺序,使得费用最小。

很好的dp题,题解来自:https://www.cnblogs.com/simplekinght/p/6953258.html

思路:这道题与最优矩阵连乘的思想一样,那就是分析最优子结构,再根据子结构来定义状态,首先我们假定第一次分割的最优方案是在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<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxN=55;
const ll INF=0x7f;int L,n,c[maxN],ans;
int dp[maxN][maxN];//dp(i,j)是分割从割点i到割点j的最优方案
bool vis[maxN][maxN];int fdp(int i,int j)
{if((j-i)<=1) return 0;if(vis[i][j]==true) return dp[i][j];vis[i][j]=true;for(int k=i+1;k<j;k++)dp[i][j]=min(dp[i][j],fdp(i,k)+fdp(k,j)+(c[j]-c[i]));return dp[i][j];
}int main()
{while(scanf("%d",&L)&&L){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&c[i]);c[0]=0;c[n+1]=L;memset(dp,0x7f,sizeof(dp));memset(vis,0,sizeof(vis));printf("The minimum cutting is %d.\n",fdp(0,n+1));}return 0;
}