P3622 [APIO2007]【一本通提高状态压缩类动态规划】动物园
广告
绿树公司 - 官方网站:https://wangping-lvshu.github.io/LvshuNew/
绿树智能 - 官方网站:https://wangping-lvshu.github.io/LvshuZhineng/
(现在使用,人人均可获得300元大奖)
[APIO2007] 动物园
题目描述
新建的圆形动物园是亚太地区的骄傲。圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围栏里有一
 种动物。如下图所示:

你是动物园的公共主管。你要做的是,让每个来动物园的人都尽可能高兴。今天有一群小朋友来动物园参观,你希望能让他们在动物园度过一段美好的时光。但这并不是一件容易的事——有的动物有一些小朋友喜欢,有的动物有一些小朋友害怕。如, Alex \texttt{Alex} Alex 喜欢可爱的猴子和考拉,而害怕拥牙齿锋利的狮子。而 Polly \texttt{Polly} Polly 会因狮子有美丽的鬃毛而喜欢它,但害怕有臭味的考拉。你可以选择将一些动物从围栏中移走以使得小朋友不会害怕。但你不能移走所有的动物,否则小朋友们就没有动物可看了。每个小朋友站在大围栏圈的外面,可以看到连续的 5 5 5 个围栏。你得到了所有小朋友喜欢和害怕的动物信息。当下面两处情况之一发生时,小朋友就会高兴:
- 至少有一个他害怕的动物被移走
 - 至少有一个他喜欢的动物没被移走
 
例如,考虑下图中的小朋友和动物:

- 假如你将围栏 4 4 4 和 12 12 12 的动物移走。 Alex \texttt{Alex} Alex 和 Ka-Shu \texttt{Ka-Shu} Ka-Shu 将很高兴,因为至少有一个他们害怕的动物被移走了。这也会使 Chaitanya \texttt{Chaitanya} Chaitanya 高兴,因为他喜欢的围栏 6 6 6 和 8 8 8 中的动物都保留了。但是, Polly \texttt{Polly} Polly 和 Hwan \texttt{Hwan} Hwan 将不高兴,因为他们看不到任何他们喜欢的动物,而他们害怕的动物都还在。这种安排方式使得三个小朋友高兴。
 - 现在,换一种方法,如果你将围栏 4 4 4 和 6 6 6 中的动物移走, Alex \texttt{Alex} Alex 和 Polly \texttt{Polly} Polly 将很高兴,因为他们害怕的动物被移走了。 Chaitanya \texttt{Chaitanya} Chaitanya 也会高兴,虽然他喜欢的动物 6 6 6 被移走了,他仍可以看到围栏 8 8 8 里面他喜欢的动物。同样的 Hwan 也会因可以看到自己喜欢的动物 12 12 12 而高兴。唯一不高兴的只有 Ka-Shu \texttt{Ka-Shu} Ka-Shu。
 - 如果你只移走围栏 13 13 13 中的动物, Ka-Shu \texttt{Ka-Shu} Ka-Shu 将高兴,因为有一个他害怕的动物被移走了, Alex \texttt{Alex} Alex, Polly \texttt{Polly} Polly, Chaitanya \texttt{Chaitanya} Chaitanya 和 Hwan \texttt{Hwan} Hwan 也会高兴,因为他们都可以看到至少一个他们喜欢的动物。所以有 5 5 5 个小朋友会高兴。这种方法使得了最多的小朋友高兴。
 
输入格式
输入的第一行包含两个整数 N N N, C C C,用空格分隔。
N N N 是围栏数( 10 ≤ N ≤ 1 0 4 10 \le N \le 10^4 10≤N≤104), C C C 是小朋友的个数( 1 ≤ C ≤ 5 × 1 0 4 1 \le C \le 5\times 10^4 1≤C≤5×104)。
围栏按照顺时针的方向编号为 1 , 2 , 3 , ⋯ , N 1,2,3,\cdots,N 1,2,3,⋯,N。
接下来的 C C C 行,每行描述一个小朋友的信息,以下面的形式给出: E , F , L , X 1 , X 2 , ⋯ , X F , Y 1 , Y 2 , ⋯ , Y L E, F, L ,X_1, X_2 ,\cdots ,X_F ,Y_1 ,Y2 ,\cdots ,Y_L E,F,L,X1,X2,⋯,XF,Y1,Y2,⋯,YL。
其中: E E E 表示这个小朋友可以看到的第一个围栏的编号( 1 ≤ E ≤ N 1 \le E \le N 1≤E≤N),换句话说,该小朋友可以看到的围栏为 E E E, E + 1 E+1 E+1, E + 2 E+2 E+2, E + 3 E+3 E+3, E + 4 E+4 E+4。
注意,如果编号超过 N N N 将继续从 1 1 1 开始算。
如:当 N = 14 N=14 N=14, E = 13 E=13 E=13 时,这个小朋友可以看到的围栏为 13 , 14 , 1 , 2 13,14,1, 2 13,14,1,2 和 3 3 3。
F F F 表示该小朋友害怕的动物数。
L L L 表示该小朋友喜欢的动物数。
围栏 X 1 , X 2 , ⋯ , X F X_1, X_2, \cdots, X_F X1,X2,⋯,XF 中包含该小朋友害怕的动物。
围栏 Y 1 , Y 2 , ⋯ , Y L Y1, Y2, \cdots, Y_L Y1,Y2,⋯,YL 中包含该小朋友喜欢的动物。
X 1 , X 2 , ⋯ , X F , Y 1 , Y 2 , ⋯ , Y L X_1, X_2, \cdots, X_F, Y_1, Y_2, \cdots, Y_L X1,X2,⋯,XF,Y1,Y2,⋯,YL 是两两不同的整数,而且所表示的围栏都是该小朋友可以看到的。
小朋友已经按照他们可以看到的第一个围栏的编号从小到大的顺序排好了(这样最小的 E E E 对应的小朋友排在第一个,最大的 E E E 对应的小朋友排在最后一个)。
注意可能有多于一个小朋友对应的 E E E 是相同的。
输出格式
仅输出一个数,表示最多可以让多少个小朋友高兴。
输入输出样例
样例输入1
14 5 
2 1 2 4 2 6 
3 1 1 6 4 
6 1 2 9 6 8
8 1 1 9 12 
12 3 0 12 13 2 
 
样例输出1
5
 
样例输入2
12 7 
1 1 1 1 5 
5 1 1 5 7 
5 0 3 5 7 9 
7 1 1 7 9 
9 1 1 9 11 
9 3 0 9 11 1
11 1 1 11 1
 
样例输出2
6
 
说明/提示
数据范围
 对于 
    
     
      
       
        100
       
       
        %
       
      
      
       100\%
      
     
    100% 的数据,
    
     
      
       
        10
       
       
        ≤
       
       
        N
       
       
        ≤
       
       
        1
       
       
        
         0
        
        
         4
        
       
      
      
       10 \le N \le 10^4
      
     
    10≤N≤104,
    
     
      
       
        1
       
       
        ≤
       
       
        C
       
       
        ≤
       
       
        5
       
       
        ×
       
       
        1
       
       
        
         0
        
        
         4
        
       
      
      
       1 \le C \le 5\times 10^4
      
     
    1≤C≤5×104,
    
     
      
       
        1
       
       
        ≤
       
       
        E
       
       
        ≤
       
       
        N
       
      
      
       1 \le E \le N
      
     
    1≤E≤N。
样例说明
- 第一个样例是题目描述中的例子,所有的 C = 5 C=5 C=5 个小朋友都能高兴。
 - 第二个样例是一个不能使得所有 C = 7 C=7 C=7 个小朋友都高兴的例子。
 
Code
#include <bits/stdc++.h>
using namespace std;
int n, m, ans, f[50001][40], num[50001][40];
int main()
{
	cin >> n >> m;
	for (int i = 1, j, E, F, L, t, sta1, sta2; i <= m; ++i)
	{
		for (cin >> E >> F >> L, j = 1, sta1 = sta2 = 0; j <= F; ++j)
			cin >> t, t = (t - E + n) % n, sta1 |= 1 << t;
		for (j = 1; j <= L; ++j)
			cin >> t, t = (t - E + n) % n, sta2 |= 1 << t;
		for (j = 0; j < 32; ++j)
			if ((j & sta1) || (~j & sta2))
				++num[E][j];
	}
	for (int i = 0; i < 32; ans = max(f[n][i], ans), ++i)
	{
		memset(f[0], -0x3f, sizeof(f[0])), f[0][i] = 0;
		for (int j = 1; j <= n; ++j)
			for (int k = 0; k < 32; ++k)
				f[j][k] = max(f[j - 1][(k & 15) << 1], f[j - 1][(k & 15) << 1 | 1]) + num[j][k];
	}
	cout << ans;
	return 0;
}
                

                
            
        
浙公网安备 33010602011771号