首页 > 其他分享 >2022.10.21-C 放书

2022.10.21-C 放书

时间:2022-10-24 10:58:26浏览次数:46  
标签:选出 21 int rd re le now 2022.10 放书

题意

有一个长为 \(n\) 的序列 \(a\),你可以选择一个数,将它放到任意位置,共可以操作 \(m\) 次。

我们定义 \(w\) 表示不同连续段的个数,问 \(k\) 次操作后,\(w\) 的最小值是多少?

\(n,m\le 500\), \(25\le a_i\le 32\)


思路

\(a_i\) 的范围很小,提示我们向状态压缩方面想。

这道题,无非就是考虑一个数选不选出来:如果选出来,那么一定是放到一个与它相同,且没有动过的数旁边;如果不选出来,那么就看序列的末尾与它是否相同。

因此我们可以考虑设计一个状态 \(f_{i,j,k,s}\) 为最小段数,表示当前考虑到第 \(i\) 个数,操作了 \(j\) 次,当前序列末尾的数为 \(k\);\(s\) 则是状压,第 \(x\) 位为 \(1\) 当且仅当 \(i\) 及以前的 \(x\) 都被选出来操作。

因此我们可以考虑转移:

  1. \(a_i\) 选出来,从 \(f_{i-1, j-1, k, s}\) 转移过来:
  • 如果在此之前 \(a_i\) 都没出现过,显然 \(s\) 上第 \(a_i\) 位是 \(0\),这时要加上 \(2^{a_i}\),设新状态为 \(ns\)。

  • \[f_{i,j,k,ns}\leftarrow f_{i-1,j-1,k,s} \]

  1. \(a_i\) 保持不动从 \(f_{i-1, j, k, s}\) 转移过来:
  • 如果 \(s\) 的 \(a_i\) 位上为 \(1\),我们要将它改为 \(0\),因为有不动的 \(a_i\) 了。

  • \[f_{i,j,a_i,ns}\leftarrow f_{i-1,j,k,s} \]

一些细节可见代码。


代码

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define FOR(i, x, y) for(int i = (x); i <= (y); i++)
#define ROF(i, x, y) for(int i = (x); i >= (y); i--)
inline int rd()
{
	int sign = 1, re = 0; char c = getchar();
	while(!isdigit(c)) {if(c == '-') sign = -1; c = getchar();}
	while(isdigit(c)) {re = re * 10 + (c - '0'); c = getchar();}
	return sign * re;
}
inline void cxkmin(int &a, int b) {a = a > b ? b : a;}
const int S = (1 << 8) - 1;
int n, m, a[505];
int f[2][101][8][1 << 8];
bitset<8> vis;
signed main()
{
	freopen("book.in", "r", stdin);
	freopen("book.out", "w", stdout);
	n = rd(), m = rd();
	FOR(i, 1, n) a[i] = rd() - 25;
	memset(f[0], 0x3f, sizeof(f[0]));
	int pres = 0;
	FOR(i, 1, n)
	{
		int now = i & 1, la = now ^ 1;
		memset(f[now], 0x3f, sizeof(f[now]));
		FOR(j, 1, m) FOR(k, 0, 7) FOR(x, 0, S) if(f[la][j - 1][k][x] != 0x3f3f3f3f)
		{
			int nx = x;
			if(!(x & (1 << a[i])) && !vis[a[i]]) nx ^= (1 << a[i]);
			cxkmin(f[now][j][k][nx], f[la][j - 1][k][x]);
		}
		FOR(j, 0, m) FOR(k, 0, 7) FOR(x, 0, S) if(f[la][j][k][x] != 0x3f3f3f3f)
		{
			int nx = x;
			if(x & (1 << a[i])) nx ^= (1 << a[i]);
			cxkmin(f[now][j][a[i]][nx], f[la][j][k][x] + (k != a[i]));
		}
		vis[a[i]] = 1;
		if(i - 1 <= m) cxkmin(f[now][i - 1][a[i]][pres], 1);
		pres |= 1 << a[i];
	}
	int ans = 0x3f3f3f3f;
	FOR(j, 0, m) FOR(k, 0, 7)
		cxkmin(ans, f[n & 1][j][k][0]);
	printf("%d", ans);
	return 0;
}

标签:选出,21,int,rd,re,le,now,2022.10,放书
From: https://www.cnblogs.com/zuytong/p/16820747.html

相关文章

  • 2022.10.24
    2022.10.24生日快乐!!!嘿嘿嘿。稍微写一哈。早上做核酸,聂老师又发火了,因为我们不看红绿灯。好吧,这确实是我们的错。虽然但是,更愿意被老吕训,而不愿意听聂老师巴巴。昨天......
  • AcWing 1221 四平方和
    \(AcWing\)\(1221\).四平方和+自定义排序(重载<)+二分题目传送门一、题目大意四平方和定理,又称为拉格朗日定理:每个正整数都可以表示为至多\(4\)个正整数的平方和......
  • 2022.10.20-C 二叉树
    题意有一颗二叉树,满足一个结点要么是叶子结点,要么有两个儿子。同时,不存在一个叶子结点,使得它到根的路径上经过了\(\gem\)条向左的边。(左右子树有区别)对于\(1\lek\l......
  • 2022-2023-1 20221317《计算机基础与程序设计》第九周学习总结
    作业信息这个作业属于哪个课程:首页-2022-2023-1-计算机基础与程序设计-北京电子科技学院-班级博客-博客园(cnblogs.com)这个作业的要求在:2022-2023-1《计算......
  • 2022.10.20-B 排序
    题意一个长为\(n\)的排列,第\(i\)个位置上的数是\(p_i\);花费\(a_i\)的代价将数字\(i\)移到任意位置;花费\(b_i\)的代价将数字\(i\)移到左端;花费\(c_i\)的......
  • 2022.10.21 模拟赛小结
    2022.10.21模拟赛小结目录2022.10.21模拟赛小结更好的阅读体验戳此进入赛时思路T1CodeT2CodeT3CodeT4Code正解T2CodeT3T4UPDsssmzyAK了,zpair差一点AK了,我寄了。......
  • 2022.10.19 模拟赛小结
    2022.10.19模拟赛小结目录2022.10.19模拟赛小结更好的阅读体验戳此进入赛时思路T1CodeT2T3T4Code正解T1CodeT2T3T4CodeUPD(一场难度稍微低1丶丶的模拟赛,不过我太弱了,......
  • 2022.10.14 模拟赛小结
    2022.10.14模拟赛小结目录2022.10.14模拟赛小结题面PDF链接更好的阅读体验戳此进入赛时思路T1T2CodeT3CodeT4正解T1CodeT2CodeT3T4UPD大概是相对来讲补的比较全的一场......
  • 2022-2023-1 20221316《计算机基础与程序设计》第八周学习总结
    作业信息<班级的链接>首页-2022-2023-1-计算机基础与程序设计-北京电子科技学院-班级博客-博客园<作业要求的链接>:https://www.cnblogs.com/rocedu/p/9577842.h......
  • 2022-2023-1 20221312 《计算机基础与程序设计》第八周学习总结
    班级链接:首页-2022-2023-1-计算机基础与程序设计-北京电子科技学院-班级博客-博客园(cnblogs.com)作业要求:2022-2023-1《计算机基础与程序设计》教学进程-娄......