UVA - 10051Tower of Cubes(递推)

来源:互联网 发布:java 多个变量初始化 编辑:程序博客网 时间:2024/05/29 21:28

题目: UVA - 10051Tower of Cubes(递推)


题目大意:给出N个正方体1-N,只有序号小的正方体可以放在序号大的正方体的上面,并且除了最底下的那个正方体,其他的正方体的底面要和它下面的正方体的上面颜色相同。问怎样组合才能使得用的正方体个数越多。并且输出其中的一种堆放方式。


解题思路:一开始觉得是用DAG上的DP来做,结果状态开太多dp【N】【N】【M】(N代表正方体个数, M代表六个面),最后输出路径的时候超时了。后面看了别人的题解,发现状态只需要开dp[N][M]就足够了,因为只要在意这个正方体是哪个面在上面,下面的正方体的范围是确定的,那么组成方式最优的肯定是确定的。不需要将下面接着哪个正方体也记录下来。

                  状态转移方程:dp【i】【k】 = (dp【i + n】【m】 + 1) m:和第i个正方体底面颜色相同的i + n个正方体的那个面。 i  + n 代表i之后的正方体从哪个开始。意思就是从i之后的正方体任选一个作为i后面的那个正方体,然后在用这个i + n的正方题的m面朝上的最多的个数再加上1.

                 初始化的时候要小心,dp【i】【k】 = 1[(i >= 1 && i <= N) (k >= 0 && k < M)】只取一个的时候,任何一个正方体哪个面朝上的组合方式的最多的个数是1。

                 这题的路径打印也是很无语,还得先找到对的路径,然后用next【j】(j这个立方体后面接哪个立方体最优),和side【j】(j这个立方体哪个面朝上最优)记录下来,最后在打印出来。


代码:

#include <cstdio>#include <cstring>const int N = 505;const int M = 6;const char str[M][2 * M] = {"front", "left", "top", "bottom", "right", "back"};int n;int cube[N][M];int dp[N][M];int next[N], side[N];int Max (const int a, const int b) {return a > b? a: b;}bool printf_ans (int d, int k) {if (dp[d][k] == 1) {next[d] = d;return true;}for (int j = d + 1; j <= n; j++) for (int i = 0; i < M; i++)if (cube[d][M - 1 - k] == cube[j][i] && dp[d][k] == dp[j][i] + 1) {if (printf_ans(j, i)) {next[d] = j;side[j] = i;return true;}}return false;}int main () {int cas = 0;while (scanf ("%d", &n) , n) {if (cas)printf ("\n");for (int i = 1; i <= n; i++) {for (int j = 0; j < M/2; j++)scanf ("%d%d", &cube[i][j], &cube[i][M - 1 - j]);}//initfor (int j = 1; j <= n; j++)for (int i = 0; i < M; i++)dp[j][i] = 1;int ans = 1;int d, k;for (int i = n - 1; i >= 1; i--)for (int j = 0; j < M; j++) {for (int l = i + 1; l <= n; l++) { for (int k = 0; k < M; k++)if (cube[i][M - 1 - j] == cube[l][k]) {if (dp[l][k] + 1 > dp[i][j]) {dp[i][j] = Max (dp[i][j], dp[l][k] + 1);}}} if (dp[i][j] > ans) {d = i;k = j;ans = dp[i][j];}}printf ("Case #%d\n%d\n", ++cas, ans);//pathif (ans == 1) {printf ("1 front\n");continue;}printf_ans (d, k);while (1) {printf ("%d %s\n", d, str[k]);if (d == next[d])break;d = next[d];k = side[d];}}return 0;}


0 0
原创粉丝点击