UVa 10271 Chopsticks(经典DP)
题意:
有n个数据,给定k,要从中选出k+8个三元组(x,y,z,其中x<=y<=z),每选一次的代价为(x-y)^2,求最小代价和。
思路:
属于比较经典的一类动态规划了,首先是状态转移方程要思考清楚,然后就是题目本身的一些限制条件。
dp[i, j]表示前i个筷子选择j对(x, y, z)差值最小。
对于第i个筷子,就要考虑清楚了,第i个筷子参与第j对 与 第i个筷子不参与第j对。
dp[i][j] = min(dp[i-1][j], dp[i-2][j-1] + w);
初始化状态要搞清楚,dp[i, 0] = 0,因为要满足选择k+8组,所以其他的都要赋值INT_MAX;
师兄说,所有的数学问题都可以用数学归纳法解决,从小的方面入手或者说一步一步分析,步伐不要太大,
就可以一个很抽象的问题简单化。毕竟再复杂的问题都是可以由各个小问题叠加过来的。强大的数学思想,还有待于训练到编程中来。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#define min(a,b) (((a) < (b)) ? (a) : (b))
int dp[5010][1010];
int a[5010];
int main()
{
int cases;
scanf("%d", &cases);
while (cases--)
{
int k, n;
scanf("%d %d", &k, &n);
k += 8;
for (int i = n; i >= 1; --i)
scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i)
{
dp[i][0] = 0;
for (int j = 1; j <= k; ++j)
dp[i][j] = INT_MAX;
}
for (int i = 3; i <= n; ++i)
for (int j = 1; j <= k; ++j)
if (i >= j * 3 && dp[i-2][j-1] != INT_MAX)
dp[i][j] = min(dp[i-1][j], dp[i-2][j-1] + (a[i]-a[i-1]) * (a[i]-a[i-1]));
printf("%d\n", dp[n][k]);
}
return 0;
}
-------------------------------------------------------
kedebug
Department of Computer Science and Engineering,
Shanghai Jiao Tong University
E-mail: kedebug0@gmail.com
GitHub: http://github.com/kedebug
-------------------------------------------------------