首页 > 代码库 > UVA 10003 区间DP
UVA 10003 区间DP
这个题目蛮有新意的,一度导致我没看透他是区间DP
给一个0-L长度的木板,然后给N个数,表示0-L之间的某个刻度,最后要用刀把每个刻度都切一下 使其断开,然后每次分裂的cost是分裂前的木板的长度。求整个分开之后的最小cost。
当时下意识就想到类似花瓶插花问题,即dp[i][j],表示第i个事物放在第j次动作来的最小代价,但是当我写起来发现很麻烦,我是以刻度点来表示的i,结果发现处理起来相当麻烦,因为实体实际是一块一块的小木板,以点作为转移变量 不仅要加诸多限制,而且加完后发现会互相矛盾,原因在于点本身不稳定,他的切割不仅涉及次数,还涉及左右板块的各种组合可能。
后来想了一下,此题反过来想,其实是从小木块堆叠成大木块,从单个的组合为成对的 然后组合成3个或者4个的。。。这不是就个区间dp吗。。然后问题就变得超级简单啦。。。连我都不相信原本让我写的这么复杂的。。反过来一想就这么几行。。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int dp[55][55];int L,sz[55][2];int A[55],n;int main(){ while (scanf("%d",&L) && L) { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&A[i]); memset(dp,-1,sizeof dp); A[n+1]=L; n++; sort(A+1,A+n+1); for (int i=1;i<=n;i++){ sz[i][0]=sz[i-1][1]; sz[i][1]=A[i]; dp[i][i]=0; } for (int i=1;i<n;i++){ for (int j=1;j+i<=n;j++){ int k=j+i; int val=sz[k][1]-sz[j][0]; for (int w=j;w<=k;w++){ int tmp=dp[j][w]+dp[w+1][k]+val; if (dp[j][k]<0){ dp[j][k]=tmp; } else{ dp[j][k]=min(dp[j][k],tmp); } } } } printf("The minimum cutting is %d.\n",dp[1][n]); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。