zoukankan      html  css  js  c++  java
  • 洛谷P3622 动物园

    题意:给定一个n个元素的圈,m个条件。满足一个条件需要选某些元素或不选另一些元素。

    问最多能满足多少条件。每个条件所关联的元素,最远的两个距离不会超过5。

    解:想了半天......

    首先能想到断环成链DP。

    然后某个时刻灵光一闪,突然发现可以状压最近的5个位置......这样枚举开始位置做32次DP就行了!

    实现的时候发现只要枚举16种开始情况,状压4个位置...

    转移就是考虑下一个位置选/不选。

    注意细节......为什么有人20行A题,我写了160行呀...

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <vector>
      4 #include <algorithm>
      5 
      6 const int N = 10010;
      7 
      8 struct Node {
      9     int p, fear, like;
     10     int a[5]; // 0 none  1 fear  2 like
     11 }node[5 * N];
     12 
     13 int f[N][16], n;
     14 std::vector<int> v[N];
     15 
     16 inline void exmax(int &a, int b) {
     17     a < b ? a = b : 0;
     18     return;
     19 }
     20 
     21 inline void out(int x, int tag) {
     22     printf(" ");
     23     for(int i = 0; i < tag; i++) {
     24         printf("%d", (x >> i) & 1);
     25     }
     26     printf(" ");
     27     return;
     28 }
     29 
     30 inline int check(Node x, int s) {
     31     for(int i = 0; i < 5; i++) {
     32         if(x.a[i] == 1 && ((s >> i) & 1)) {
     33             return 1;
     34         }
     35         if(x.a[i] == 2 && (((s >> i) & 1) == 0)) {
     36             return 1;
     37         }
     38     }
     39     return 0;
     40 }
     41 
     42 int main() {
     43 
     44     int m;
     45     scanf("%d%d", &n, &m);
     46     for(int i = 1, x; i <= m; i++) {
     47         scanf("%d%d%d", &node[i].p, &node[i].fear, &node[i].like);
     48         node[i].p += 4;
     49         while(node[i].p > n) {
     50             node[i].p -= n;
     51         }
     52         for(int j = 1; j <= node[i].fear; j++) {
     53             scanf("%d", &x);
     54             for(int k = 4, now = node[i].p + 1; k >= 0; k--) {
     55                 now--;
     56                 if(!now) {
     57                     now = n;
     58                 }
     59                 if(now == x) {
     60                     node[i].a[k] = 1;
     61                     break;
     62                 }
     63             }
     64         }
     65         for(int j = 1; j <= node[i].like; j++) {
     66             scanf("%d", &x);
     67             for(int k = 4, now = node[i].p + 1; k >= 0; k--) {
     68                 now--;
     69                 if(!now) {
     70                     now = n;
     71                 }
     72                 if(now == x) {
     73                     node[i].a[k] = 2;
     74                     break;
     75                 }
     76             }
     77         }
     78         v[node[i].p].push_back(i);
     79     }
     80     /// input
     81     int ans = 0;
     82     /// -----
     83     /// 01234
     84     for(int op = 0; op < 16; op++) { /// first four
     85         memset(f, 0, sizeof(f));
     86         for(int s = 0; s < 16; s++) {
     87             if(s != op) {
     88                 f[4][s] = -1;
     89             }
     90         }
     91 
     92         for(int i = 4; i < n; i++) {
     93             for(int s = 0; s < 16; s++) {
     94                 if(f[i][s] == -1) {
     95                     continue;
     96                 }
     97                 /// f[i][s] -> f[i + 1][t]
     98                 
     99                 int t = s >> 1, temp = f[i][s]; /// put 0  don't move
    100                 for(int j = 0; j < v[i + 1].size(); j++) {
    101                     /// node[v[i + 1][j]]  and  s
    102                     temp += check(node[v[i + 1][j]], s);
    103                 }
    104                 exmax(f[i + 1][t], temp);
    105                 // -------------------------------------
    106                 t = t | (1 << 3); /// put 1  move
    107                 temp = f[i][s];
    108                 for(int j = 0; j < v[i + 1].size(); j++) {
    109                     temp += check(node[v[i + 1][j]], s | (1 << 4));
    110                 }
    111                 exmax(f[i + 1][t], temp);
    112             }
    113         }
    114         for(int s = 0; s < 16; s++) {
    115             /// f[n][s]
    116             int temp = f[n][s], now = s << 1;
    117             for(int i = 0; i < 4; i++) {
    118                 now = (now >> 1) + (((op >> i) & 1) << 4);
    119                 for(int j = 0; j < v[i + 1].size(); j++) {
    120                     temp += check(node[v[i + 1][j]], now);
    121                 }
    122             }
    123             exmax(ans, temp);
    124         }
    125     }
    126     printf("%d
    ", ans);
    127     return 0;
    128 }
    AC代码
  • 相关阅读:
    ArrayList removeRange方法分析
    LinkedHashMap源码分析(基于JDK1.6)
    LinkedList原码分析(基于JDK1.6)
    TreeMap源码分析——深入分析(基于JDK1.6)
    51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划
    51 NOD 1049 最大子段和 动态规划 模板 板子 DP
    51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
    8月20日 训练日记
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10383076.html
Copyright © 2011-2022 走看看