ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

作业【状压DP】

2021-09-27 17:02:12  阅读:162  来源: 互联网

标签:cnt ok int 状压 作业 tot jj include DP


>Link

luogu U137979


>Description
在这里插入图片描述
对于 100% 的数据, 1 ≤ b i ≤ n ≤ 18 , 1 ≤ a i ≤ 10 1 ≤b_i ≤ n ≤ 18, 1 ≤ a_i ≤ 10 1≤bi​≤n≤18,1≤ai​≤10


>解题思路

一开始没看数据范围想了好久QAQ

然后一看这个数据范围应该就是状压DP
设 f s , i f_{s,i} fs,i​为在 s s s状态下,最后一个写的作业为第 i i i个的方案数,状态 s s s记录对应的作业有没有写
直接按照题意暴力判断当前枚举到的 s s s和 i i i是否合法
第二个条件我们发现是求当前 s s s状态下,某段区间的0的个数,可以预处理每个状态下0的前缀和,DP时 O ( 1 ) O(1) O(1)查询


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 25
using namespace std;

const int Mod = 4921057;
int n, a[N], b[N], sum[N], f[300000][N], T, minn, ans;
int tot[300000][N];

int main()
{
	int cnt, l, r; bool ok;
	minn = 10;
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++)
	  scanf ("%d", &a[i]), sum[a[i]]++, minn = min (minn, a[i]);
	for (int i = 1; i <= n; i++) scanf ("%d", &b[i]);
	for (int i = 1; i <= 10; i++) sum[i] += sum[i - 1];
	
	T = (1 << n) - 1;
	for (int i = 1; i <= T; i++)
	  for (int j = 1; j <= n; j++)
	  {
	  	tot[i][j] = tot[i][j - 1];
	  	if (((i >> (j - 1)) & 1) == 0) tot[i][j]++;
	  }
	for (int i = 1; i <= n; i++)
	  if (a[i] == minn) f[1 << (i - 1)][i] = 1;
	for (int i = 1; i <= T; i++)
	  for (int j = 1; j <= n; j++)
	  {
	  	if (((i >> (j - 1)) & 1) == 0) continue;
	  	cnt = 0, ok = 1;
	  	for (int jj = 1; jj <= n; jj++)
	  	  if ((i >> (jj - 1)) & 1)
	  	  {
	  	  	if (a[jj] > a[j]) {ok = 0; break;}
	  	  	cnt++;
		  }
		if (!ok || cnt <= sum[a[j] - 1]) continue;
		int ii = i ^ (1 << (j - 1));
		for (int jj = 1; jj <= n; jj++)
		{
	  		if (((ii >> (jj - 1)) & 1) == 0) continue;
	  		/*cnt = 0;
	  		for (int t = min (j, jj) + 1; t < max (j, jj); t++)
	  		  if (((ii >> (t - 1)) & 1) == 0) cnt++;
	  		if (cnt <= b[jj]) f[i][j] = (f[i][j] + f[ii][jj]) % Mod;*/
	  		l = min (j, jj) + 1, r = max (j, jj) - 1;
	  		if (tot[ii][r] - tot[ii][l - 1] <= b[jj])
	  		  f[i][j] = (f[i][j] + f[ii][jj]) % Mod;
		}
	  }
	for (int i = 1; i <= n; i++)
	  ans = (ans + f[T][i]) % Mod;
	printf ("%d", ans);
	return 0;
}

标签:cnt,ok,int,状压,作业,tot,jj,include,DP
来源: https://blog.csdn.net/qq_43010386/article/details/120512299

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有