zoukankan      html  css  js  c++  java
  • BZOJ 3982 Stacking Plates 解题报告

    我们首先可以得到:如果有一堆盘子里有一些相邻的盘子的直径相等,那么自然这些盘子可以统一处理,就可以缩成一个了。

    然后我们接着考虑给每一堆盘子都染上一种颜色,那么操作的次数 step = diff * 2 - n + 1

    其中 diff 表示最终的盘子堆中相邻的盘子的颜色不同的对数。

    接着我们可以将盘子的直径离散化。

    那么我们可以考虑Dp,设 Dp[s][i] 为处理完所有盘子直径小于等于 s 的盘子,并且最底下的盘子的颜色是 i 的 diff 的最小值。

    至于转移的话呢,记直径为 s 的盘子个数为 tot[s],然后找到所有直径为 s 的盘子及其颜色 i ,那么就有:

    • res1 = min(Dp[s - 1][j] + tot[s]) (j = 1 ~ n)
    • res2 = min(Dp[s - 1][k] + tot[s] - 1) (存在一个直径为 s,颜色为 k 的盘子)
    • Dp[s][i] = min(res1, res2)

    初始化 Dp[0][i] = 0 (i = 1 ~ n)

    答案 ans = min(Dp[Max_s][i]) * 2 - n + 1 

    于是就做完啦~

    毕竟 Gromah 太弱,只会做水题。

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 #define N 50 + 5
     8 #define M 2500 + 5
     9 #define SIZE 10000 + 5
    10 #define INF 593119681
    11 
    12 int _, n;
    13 int A[N][N];
    14 int Size[N], Point[N], T[N];
    15 int Dp[2][N];
    16 int S[SIZE];
    17 
    18 inline void Init()
    19 {
    20     memset(S, 0, sizeof(S));
    21     for (int i = 1; i <= n; i ++)
    22     {
    23         scanf("%d", Size + i);
    24         for (int j = 1; j <= Size[i]; j ++)
    25         {
    26             scanf("%d", A[i] + j);
    27             S[A[i][j]] = 1;
    28         }
    29         Size[i] = unique(A[i] + 1, A[i] + Size[i] + 1) - A[i] - 1;
    30         Point[i] = 1;
    31     }
    32     for (int i = 1; i < SIZE; i ++)
    33         S[i] += S[i - 1];
    34     for (int i = 1; i <= n; i ++)
    35         for (int j = 1; j <= Size[i]; j ++)
    36             A[i][j] = S[A[i][j]];
    37 }
    38 
    39 inline void Solve()
    40 {
    41     printf("Case %d: ", ++ _);
    42     for (int i = 0; i <= n; i ++)
    43         Dp[0][i] = 0;
    44     for (int i = 1; i <= S[SIZE - 1]; i ++)
    45     {
    46         T[0] = 0;
    47         Dp[1][0] = INF;
    48         for (int j = 1; j <= n; j ++)
    49         {
    50             if (A[j][Point[j]] == i)
    51                 T[++ T[0]] = j, Point[j] ++;
    52             Dp[1][j] = INF;
    53         }
    54         for (int j = 1; j <= T[0]; j ++)
    55         {
    56             for (int k = 1; k <= T[0]; k ++)
    57             {
    58                 if (j == k && T[0] > 1) continue ;
    59                 Dp[1][T[k]] = min(Dp[1][T[k]], Dp[0][T[j]] + T[0] - 1);
    60             }
    61             for (int k = 0; k <= n; k ++)
    62                 Dp[1][T[j]] = min(Dp[1][T[j]], Dp[0][k] + T[0]);
    63         }
    64         for (int j = 0; j <= n; j ++)
    65             Dp[0][j] = Dp[1][j];
    66     }
    67     int Min = INF;
    68     for (int i = 0; i <= n; i ++)
    69         Min = min(Min, Dp[0][i]);
    70     printf("%d
    ", Min * 2 - n + 1);
    71 }
    72 
    73 int main()
    74 {
    75     #ifndef ONLINE_JUDGE
    76         freopen("3982.in", "r", stdin);
    77         freopen("3982.out", "w", stdout);
    78     #endif
    79     
    80     while (scanf("%d", &n) == 1)
    81     {
    82         Init();
    83         Solve();
    84     }
    85     
    86     #ifndef ONLINE_JUDGE
    87         fclose(stdin);
    88         fclose(stdout);
    89     #endif
    90     return 0;
    91 }
  • 相关阅读:
    HDU 3401 Trade
    POJ 1151 Atlantis
    HDU 3415 Max Sum of MaxKsubsequence
    HDU 4234 Moving Points
    HDU 4258 Covered Walkway
    HDU 4391 Paint The Wall
    HDU 1199 Color the Ball
    HDU 4374 One hundred layer
    HDU 3507 Print Article
    GCC特性之__init修饰解析 kasalyn的专栏 博客频道 CSDN.NET
  • 原文地址:https://www.cnblogs.com/gromah/p/4424405.html
Copyright © 2011-2022 走看看