您的位置:首页 > 其它

UVA10003固定点切木棍,怎么切使得每次切之前的木棍长度总和最小

2016-04-12 19:27 274 查看
这题,刚开始想了很久没有想到怎么处理,其实如果想通了很简单的,

用d[begin][end]表示从bigin切点到end切点,这段木棍的最省钱切法,然后就模拟切中间各点,计算交给递归下一层。。。

没有后效性,记忆化搜索,子问题重叠,这三个是dp题目的基本要素。
此题,刚好是一个经典的DP题,当然既可以用递推,也可以用记忆化搜索。
有点像矩阵链乘问题,找到状态转移公式就好了dp[i][j]=max{dp[i][k]+dp[k][j]+len[j]-len[i]|i<k<j};

递推:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#define LL long long
using namespace std;
const int maxn=1e4+10;
const double eps=1e-6;
int l,num;
int main()
{
while(cin>>l&&l)
{
cin>>num;
int a[55];
int dp[55][55];
for(int i=1;i<=num;i++)
cin>>a[i];
a[0]=0;
a[num+1]=l;
memset(dp,0,sizeof(dp));
for(int l=2;l<=num+1;l++)
{
for(int i=0;i+l<=num+1;i++)
{
int j=i+l;
dp[i][j]=maxn;
for(int k=i+1;k<j;k++)
{
int cost=dp[i][k]+dp[k][j]+a[j]-a[i];
dp[i][j]=min(dp[i][j],cost);
}
}
}
printf("The minimum cutting is %d.\n",dp[0][num+1]);
}
return 0;
}
记忆化搜索:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#define LL long long
using namespace std;
const int maxn=1e4+10;
const double eps=1e-6;
int l,n ,a[55],d[55][55];
int dp(int b,int e)
{
if(d[b][e]>=0)
return d[b][e];
d[b][e]=dp(b,b+1)+dp(b+1,e)+a[e]-a[b];
for(int i=b+2;i<e;i++)
{
int tt=dp(b,i)+dp(i,e)+a[e]-a[b];
d[b][e]=min(tt,d[b][e]);
}
return d[b][e];
}
int main()
{
while(cin>>l&&l)
{
cin>>n;
for (int i = 0; i <= n + 1; i++)
for (int j = 0; j <= n + 1; j++)
if (j - i == 1)
d[i][j] = 0;
else
d[i][j] = -1;
for(int i=1;i<=n;i++)
cin>>a[i];
a[0]=0;
a[n+1]=l;
printf("The minimum cutting is %d.\n",dp(0,n+1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: