zoukankan      html  css  js  c++  java
  • WHU 1552 Seats 枚举

    题意:

      有一个年级中7个班的n个学生。

      一天,他们毫无顺序的站成一排。请计算最小的交换次数,使得 相同班的同学都站在一起。 (只有站在一起的人才能交换)

    思路:

      如果知道班级的最终排列就能在很短的时间里,计算出所需的交换次数。那么,我们只需要枚举排列即可。

      如果,a班的一个人要走到前面,那么,他必须和他前面所有其他班的人交换。

      所以,先预处理出一个数组 f[i][j] 表示 每个 i 班的前面的 j 班同学的总和。然后就可以在m(班级数) * m 的时间里求出排列需要交换的次数。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 typedef long long ll;
     8 
     9 const int MAXN = (int) 1e5+5;
    10 const ll INF = (ll)1<<60;
    11 
    12 ll f[8][8], sum[8]; //f[i][j] : i 前面有多少个 j
    13 int a[MAXN];
    14 int n;
    15 ll ans;
    16 bool vis[8];
    17 int od[8];
    18 
    19 void cal() {
    20     ll res = 0;
    21     for (int i = 1; i < 8; i++) {
    22         for (int j = 0; od[j]!=i; j++) {
    23             res += f[i][od[j]];
    24         }
    25     }
    26     ans = min(ans, res);
    27 }
    28 
    29 void dfs(int cnt) {
    30     if (7==cnt) {
    31         cal();
    32         return ;
    33     }
    34     for (int i = 1; i < 8; i++) if (!vis[i]) {
    35         vis[i] = true;
    36         od[cnt] = i;
    37         dfs(cnt+1);
    38         vis[i] = false;
    39     }
    40 }
    41 
    42 void print() {
    43     for (int i = 1; i < 8; i++) {
    44         for (int j = 1; j < 8; j++)
    45             printf("%d ", f[i][j]);
    46         puts("");
    47     }
    48 }
    49 
    50 int main() {
    51     #ifdef Phantom01
    52         freopen("WHU1552.in", "r", stdin);
    53     #endif // Phantom01
    54 
    55     while (scanf("%d", &n)!=EOF) {
    56         memset(vis, false, sizeof(vis));
    57         memset(f, 0, sizeof(f));
    58         memset(sum, 0, sizeof(sum));
    59         for (int i = 0; i < n; i++) {
    60             scanf("%d", &a[i]);
    61             sum[a[i]]++;
    62             for (int j = 1; j < 8; j++) {
    63                 f[a[i]][j] += sum[j];
    64             }
    65         }
    66 //        print();
    67         ans = INF;
    68         dfs(0);
    69         printf("%lld
    ", ans);
    70     }
    71 
    72     return 0;
    73 }
    View Code

     p.s.:当时比赛的时候有想到过枚举排列,但是不知道该怎么很快的计算交换次数,所以就没写。 收集信息和组合信息的能力还不够啊……

  • 相关阅读:
    开启JAVA学习之旅 Day1
    python二分法及小tips
    简单的注入脚本
    Requests文档 阅读笔记
    多线程
    IO操作
    异常Exception
    Map集合
    Collection集合
    泛型
  • 原文地址:https://www.cnblogs.com/Phantom01/p/3675349.html
Copyright © 2011-2022 走看看