首页 > 其他分享 >G - Cut and Reorder 状压DP

G - Cut and Reorder 状压DP

时间:2023-11-12 12:22:05浏览次数:39  
标签:25 Cut 结尾 int 状压 namespace long ans DP

我是题目链接

首先显然先一操作,然后二操作这样不会影响最终结果

一眼状压DP,选出一些a从前往后塞,f[i][j]表示选出的a状态为i,且结尾为j时最小花费

转移就看上一个状态的结尾(设为k)和当前结尾(设为j)在a里的下标是否顺着挨着(就是j=k+1),不是顺着挨着就要加个c

这样会tle

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,c,ans=1e18;
int a[25],b[25],f[1<<23][23],cnt[1<<23];
int jue(int x)
{
	return x>0?x:-x;
}
signed main()
{
	cin>>n>>c;
	for(int i=1;i<=n;++i)cin>>a[i];
	for(int i=1;i<=n;++i)cin>>b[i]; 
	for(int i=1;i<=(1<<n)-1;++i)cnt[i]=cnt[i>>1]+(i&1);
	for(int i=1;i<=(1<<n)-1;++i)
		for(int j=1;j<=n;++j)
		if(i&(1<<(j-1)))
		{
			f[i][j]=1e18;
			if(cnt[i]==1)
			{
				f[i][j]=jue(a[j]-b[1]);
			}
		}
	for(int i=1;i<=(1<<n)-1;++i)
	{
		if(cnt[i]==1)continue;
		for(int j=1;j<=n;++j)
			if(i&(1<<(j-1)))
			{
				for(int k=1;k<=n;++k)
					if(j!=k&&(i&(1<<(k-1))))
					{
						if(j==k+1)f[i][j]=min(f[i][j],f[i^(1<<(j-1))][k]+jue(a[j]-b[cnt[i]]));
						else f[i][j]=min(f[i][j],c+f[i^(1<<(j-1))][k]+jue(a[j]-b[cnt[i]]));
					}
			}
	}
	for(int i=1;i<=n;++i)ans=min(ans,f[(1<<n)-1][i]);
	cout<<ans;
	return 0;
}
/*
2 1
100 1
1 100
*/

发现k没有必要枚举,用个数组记录最小值就好啦

有人可能会说转移不是有个if条件吗,其实可以思考下,完全没影响。

这样会MLE

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,c,ans=1e18;
int a[25],b[25],f[1<<22][23],minn[1<<22],cnt[1<<22];
int jue(int x)
{
	return x>0?x:-x;
}
signed main()
{
	cin>>n>>c;
	for(int i=1;i<=n;++i)cin>>a[i];
	for(int i=1;i<=n;++i)cin>>b[i]; 
	for(int i=1;i<=(1<<n)-1;++i)cnt[i]=cnt[i>>1]+(i&1);
	for(int i=1;i<=(1<<n)-1;++i)minn[i]=1e18;
	for(int i=1;i<=(1<<n)-1;++i)
		for(int j=1;j<=n;++j)
		if(i&(1<<(j-1)))
		{
			f[i][j]=1e18;
			if(cnt[i]==1)
			{
				f[i][j]=jue(a[j]-b[1]);
				minn[i]=min(minn[i],f[i][j]);
			}
		}
	for(int i=1;i<=(1<<n)-1;++i)
	{
		if(cnt[i]==1)continue;
		for(int j=1;j<=n;++j)
			if(i&(1<<(j-1)))
			{
				if(j!=1&&(i&(1<<(j-2))))f[i][j]=min(f[i][j],f[i^(1<<(j-1))][j-1]+jue(a[j]-b[cnt[i]]));
				f[i][j]=min(f[i][j],c+minn[i^(1<<(j-1))]+jue(a[j]-b[cnt[i]]));
				minn[i]=min(minn[i],f[i][j]);
			}
	}
	cout<<minn[(1<<n)-1];
	return 0;
}
/*
2 1
100 1
2 101
*/

MLE最主要原因是f数组记录了以谁为结尾。可以改成这样,对于一个状态,枚举接下来拼接哪一连续的块(强制加个c),这样就不用记录以谁为结尾了

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,c,ans=1e18;
int a[25],b[25],f[1<<22],cnt[1<<22];
int jue(int x)
{
	return x>0?x:-x;
}
signed main()
{
	cin>>n>>c;
	for(int i=1;i<=n;++i)cin>>a[i];
	for(int i=1;i<=n;++i)cin>>b[i]; 
	for(int i=1;i<=(1<<n)-1;++i)cnt[i]=cnt[i>>1]+(i&1);
	for(int i=1;i<=(1<<n)-1;++i)f[i]=1e18;
	for(int i=0;i<=(1<<n)-1;++i)
	{
		for(int l=1;l<=n;++l)
		{
			int cost=c,z=0;
			for(int r=l;r<=n;++r)
			{
				if(i&(1<<(r-1)))break;
				cost+=jue(a[r]-b[cnt[i]+r-l+1]);
				z|=1<<(r-1);
				f[i|z]=min(f[i|z],f[i]+cost);
			}
		}
	}
	cout<<f[(1<<n)-1]-c;//这里不明白为啥减去c可以试试代码下面的样例
	return 0;
}
/*
2 1
100 1
1 100
*/

标签:25,Cut,结尾,int,状压,namespace,long,ans,DP
From: https://www.cnblogs.com/wljss/p/17826973.html

相关文章

  • 【小沐学前端】Windows下搭建WordPress(二、相关工具安装)
    1、简介WordPress是基于PHP和MySQL的免费开源内容管理系统(CMS)。它是全球使用最广泛的CMS软件,截至2019年5月,它为排名前1000万个网站中提供了超过30%的支持,并拥有在使用CMS构建的所有网站中,估计有60%的市场份额。2、搭建环境2.1Nginx配置nginx.conf,文件在nginx目录下的conf文件夹......
  • DP做题记录
    蒟蒻DP太菜了QAQ。一点体会:DP就是如何通过最少的信息确定最优解。P5664[CSP-S2019]Emiya家今天的饭思考了一下,发现第3个要求很难直接搞,于是考虑正难则反,用总方案数减去不符合要求的方案数。求总方案数:\(g_{i,j}\)表示在前\(i\)行中选\(j\)个点的方案数,则\[g_{i,j}=g_......
  • P3842-DP【黄】
    想搜索到最后一层,就必得先完成前面层的搜索任务,这构成了对状态转移的启示,即当前层的DP值应该是此前层转移过来后得到的最佳值。但这道题看数据范围应该不能用二维数组,抱着侥幸的心理我使用了动态二维数组,dpij表示以第i层第j个为终点时的答案,结果MLE了,喜提42分,详见CODE-1。后来意......
  • 状态机模型DP
    //http://ybt.ssoier.cn:8088/problem_show.php?pid=1302#include<bits/stdc++.h>usingnamespacestd;constintN=2e5+10;intdp[N][3][3],n,w[N],t;intmain(){cin>>t;while(t--){cin>>n;intres=0;memset(......
  • [题解] AT_dp_w Intervals
    Intervals有\(m\)条形如\((l,r,a)\)的限制,表示如果\(s_{[l,r]}\)中有1就会有\(a\)的价值。你要求长度为\(n\)的01串的价值的最大值。\(n,m\le2\times10^5\)。将每个限制挂到右端点上,在右端点处计算贡献。然后我们就只关心最后一个1出现的位置了。......
  • 【小沐学前端】Windows下搭建WordPress(一、相关工具下载)
    1、简介WordPress是基于PHP和MySQL的免费开源内容管理系统(CMS)。它是全球使用最广泛的CMS软件,截至2019年5月,它为排名前1000万个网站中提供了超过30%的支持,并拥有在使用CMS构建的所有网站中,估计有60%的市场份额。1.1Nginxnginx[enginex]是一个HTTP和反向代理服务器,邮件代理......
  • To_Heart—总结——连通块 dp(抑或 连续块 dp)
    简介有一类问题,他们需要计算满足在序列上插入给定顺序的元素,其贡献/限制只与两旁的元素有关,但元素插入的位置是不一定的,所以会有代价的最值和方案数的统计。而对于这类问题,我们其实可以不关心每一次插入的具体位置在哪里,而只关注他的相对位置(比如在某个数左边、在某个数左边且与......
  • DP查缺补漏之LCS状态重叠
    DP查缺补漏之\(LCS\)状态重叠状态假设\(F[i][j]\)为\(a\)串中前\(i\)个字符,\(b\)串中前\(j\)个字符构成的\(LCS\)状态转移\(F[i-1][j-1]+1\)即当且仅当\(a[i]=b[j]\)时,从两个序列的减去当前的字符加一推出\(F[i-1][j]\)不选\(a[i]\),只选\(b[j]\)\(F[i......
  • Oracle ODP.NET ConnectionString接池及连接参数
      出自: https://blog.csdn.net/qq_28570965/article/details/126935639 1.连接字符串中提供了服务器地址,端口,实例等信息,具体格式如下:DataSource=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=MyHost)(PORT=MyPort))(CONNECT_DATA=(SERVICE_NAME=MyDatasource)));UserID=M......
  • DP查缺补漏之LIS状态记录
    DP查缺补漏之\(LIS\)状态记录前置知识状态假设\(F[i]\)为以\(a[i]\)为结尾的最长上升子序列长度。状态转移\(F[i]=max(F[j]+1,F[i])(j<i)\)很好理解,即\(i\)之前的所有以\(a[j]\)结尾的最长上升子序列中取最大,再加上\(a[i]\)即加一。代码实现for(inti=1;i<=......