zoukankan      html  css  js  c++  java
  • [BZOJ5449] 序列

    题目链接:序列

    Description

    给定一个(1)~(n)的排列x,每次你可以将 (x_1, x_2, ..., x_i) 翻转。
    你需要求出将序列变为升序的最小操作次数。
    多组数据。
    数据范围 (T=5,1le nle 25)
    时间限制 (10 s)

    Solution

    数据范围这么小,我们考虑用(IDA*)优化爆搜。
    定义估价函数 (h()=sum_{i=2}^{n} [abs(x_i-x_{i-1})≠ 1])
    考虑每一次翻转,最多可以使得(abs≠1)的对数减一,所以可以拿(h())来进行估价。
    直接爆搜即可。
    复杂度 (O(能过))

    Code

    // Author: wlzhouzhuan
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define ull unsigned long long
    #define rint register int
    #define rep(i, l, r) for (rint i = l; i <= r; i++)
    #define per(i, l, r) for (rint i = l; i >= r; i--)
    #define mset(s, _) memset(s, _, sizeof(s))
    #define pb push_back
    #define pii pair <int, int>
    #define mp(a, b) make_pair(a, b)
    
    inline int read() {
      int x = 0, neg = 1; char op = getchar();
      while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
      while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
      return neg * x;
    }
    inline void print(int x) {
      if (x < 0) { putchar('-'); x = -x; }
      if (x >= 10) print(x / 10);
      putchar(x % 10 + '0');
    }
    
    int a[26], flag, n, maxd;
    int h() {
      int cnt = 0;
      for (rint i = 2; i <= n; i++) if (abs(a[i] - a[i - 1]) != 1) {
        cnt++;
      }
      return cnt;
    }
    bool check() {
      for (rint i = 2; i <= n; i++) {
        if (a[i - 1] > a[i]) {
          return 0;
        }
      }
      return 1;
    }
    void dfs(int x, int last) { // x表示操作次数,last表示上一次翻转的位置 
      if (flag) return ;
      if (x == maxd) {
        if (check()) flag = 1;
        return ;
      }
      if (x + h() > maxd) {
        return ;
      } 
      for (rint i = 2; i <= n; i++) if (i != last) {
        reverse(a + 1, a + i + 1);
        dfs(x + 1, i);
        reverse(a + 1, a + i + 1); 
      }
    }
    int main() {
      int T = read();
      while (T--) {
        n = read();
        for (int i = 1; i <= n; i++) {
          a[i] = read();
        }
        flag = 0;
        for (maxd = 0; maxd <= 30; maxd++) {
          dfs(0, 0);
          if (flag) break;
        }
        printf("%d
    ", maxd);
      }
      return 0;
    }
    
  • 相关阅读:
    C#基础笔记(第十四天)
    C#基础笔记(第十三天)
    C#基础整理(二)
    C#基础笔记(第十二天)
    C#基础笔记(第十一天)
    C#基础笔记(第十天)
    C#基础笔记(第九天)
    [PyTorch 学习笔记] 2.3 二十二种 transforms 图片数据预处理方法
    [PyTorch 学习笔记] 2.2 图片预处理 transforms 模块机制
    [PyTorch 学习笔记] 2.1 DataLoader 与 DataSet
  • 原文地址:https://www.cnblogs.com/wlzhouzhuan/p/12755129.html
Copyright © 2011-2022 走看看