zoukankan      html  css  js  c++  java
  • 某题目2 状压DP

    Description

    对于一个数列,其混乱度定义为连续相等的数的段数。如:1 2 1 2 1,其混乱度为5,而:1 2 2 3 3,其混乱度为3。现给出一个数列,允许取出k个数并允许插入数列中的任意一个位置,要求该数列的混乱度尽量小,并求出这个最小混乱度。

    对于100%的数据:1 <= k <= n <= 100,所有数均在[25,32]内。

    Solution

    由于取出一个数i,你可以放在左边和右边,你不知道放在哪里才是最优的?

    那么我们可以直接把要取的全部取出来,最后再插进数列中。

    设F[i][j][k][s]表示做到第i个数,当前数列最后的数为j,取出了k个数,当前数列中数的集合为s的最小混乱度。

    转移很简单:

    1、第i+1个数取出:F[i+1][j][k+1][s] = min(F[i+1][j][k+1][s], F[i][j][k][s]);

    2、第i个数放在最后面:F[i+1][a[i+1]][k][s|(1<<i)] = min(F[i+1][a[i+1]][k][s|(1<<i)], F[i][j][k][s]+(a[i+1] != j));

    最后只需要把最后状态没有出现的数集合算上就好。

    Code

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <string>
     5 #include <algorithm>
     6 
     7 using namespace std;
     8 
     9 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    10 #define mset(a, b) memset(a, b, sizeof(a))
    11 int n, lim, a[105];
    12 int f[105][15][105][1<<8];
    13 int s_cnt;
    14 bool vis[10];
    15 
    16 void Ckmin(int &AI, const int &BI) { if (AI > BI) AI = BI; }
    17 
    18 int calc(int x)
    19 {
    20     int t_cnt = 0;
    21     while (x > 0)
    22     {
    23         if (x&1) t_cnt ++;
    24         x >>= 1;
    25     }
    26     return s_cnt-t_cnt;
    27 }
    28 
    29 int main()
    30 {
    31     scanf("%d %d", &n, &lim);
    32     REP(i, 1, n) scanf("%d", &a[i]), a[i] -= 25;
    33     REP(i, 1, n) if (!vis[a[i]]) vis[a[i]] = 1, s_cnt ++;
    34     REP(i, 0, n)
    35         REP(j, 0, 8)
    36             REP(k, 0, lim)
    37                 REP(s, 0, (1<<8)-1) f[i][j][k][s] = 10000;
    38     f[0][8][0][0] = 0;
    39     REP(i, 0, n-1)
    40         REP(j, 0, 8)
    41             REP(k, 0, lim)
    42                 REP(s, 0, (1<<8)-1)
    43                     if (f[i][j][k][s] < 10000)
    44                     {
    45                         if (s&(1<<a[i+1]))
    46                         {
    47                             if (j == a[i+1]) Ckmin(f[i+1][j][k][s], f[i][j][k][s]);        
    48                             else 
    49                             {
    50                                 if (k < lim) Ckmin(f[i+1][j][k+1][s], f[i][j][k][s]);
    51                                 Ckmin(f[i+1][a[i+1]][k][s], f[i][j][k][s]+1);
    52                             }
    53                         }
    54                         else
    55                         {
    56                             if (k < lim) Ckmin(f[i+1][j][k+1][s], f[i][j][k][s]);
    57                             Ckmin(f[i+1][a[i+1]][k][s|(1<<a[i+1])], f[i][j][k][s]+1);
    58                         }
    59                     }
    60     int ans = 10000;
    61     REP(j, 0, 7)
    62         REP(k, 0, lim)
    63             REP(s, 0, (1<<8)-1)
    64                 Ckmin(ans, f[n][j][k][s]+calc(s));
    65     printf("%d
    ", ans);
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    maven之私服搭建
    maven之自定义archetype
    maven之自定义插件
    任务调度之 Elastic Job
    雪花算法原理解析
    基于 zxing 的二维码生成、解析
    spring-cloud-oauth2 认证授权
    spring security 自定义短信验证登录
    spring security session管理
    JDK1.8之HashMap实现原理
  • 原文地址:https://www.cnblogs.com/-ZZB-/p/6635659.html
Copyright © 2011-2022 走看看