【JZOJ B组】教主的难题

7 篇文章 0 订阅
1 篇文章 0 订阅

Description
  一个数x可以按以下规则生成数字:
  1、将任意两位交换,若交换的数字为a和b,生成的代价为((a and b)+(a xor b))*2。
  例如134可以生成431,因为431可以从134的个位(4)与百位(1)交换后得到,代价为((1 and 4)+(1 xor 4))*2=10。
  2、将其中一位数删除,但是删除的数要满足大于等于它左边的数,且小等于它右边的数,并且定义最高位左边的数为个位,个位右边的数为最高位。若删除的数字为a,它左边的数为b,它右边的数为c,则生成的代价为a+(b and c)+(b xor c)。
  例如212,可以删除个位的数得到21,但是因为2>1,所以1是不能被删除的。特别地,若x为两位数,它能删除当且仅当x的两位数相同,若x为一位数,它是不能被删除的。
  3、在两位数字之间,也可以是数字的前面或后面加入一位数,同样地,加入的数要满足大等于它左边的数,且小等于它右边的数,并且定义最高位左边的数为个位,个位右边的数为最高位。若加入的数字为a,它左边的数为b,它右边的数为c,则生成的代价为a+(b and c)+(b xor c)。
  例如241,它可以在2与4之间加入一个3,生成2341,也可以在数的末尾加入一个1或者2,当然还有其它可以生成的数,但是不能在4和1之间加入数字。
  你的任务是,S一开始为n个不同的给定数组成的集合,每次可以从S中取出一个数生成一个满足生成规则的数加入S中,并且取出的数仍然存在于S中。生成的数的位数不能大于S初始集合最大的数的位数。问在S元素最多的情况下,总代价最小是多少。

Input
  输入的第1行为一个正整数n,为集合S初始元素个数。
  第2行包含n个正整数a1,a2, …, an,数之间空格隔开,为S中初始元素。

Output
  输出包括一个正整数,为最小代价。

Sample Input
2
111 22

Sample Output
12

Data Constraint

Hint
【样例说明】
  111删除1得到11,代价为2,11删除1得到1,代价为2,同样22删除和加入一个2得到2,222,代价均为4,总代价2+2+4+4=12。111无法生成1111因为111为一个3位数,而1111为一个4位数。
  利用交换/添加规则无法让集合元素更多,所以最小代价为12。

【数据规模】
  对于20%的数据,有ai<100;
  对于40%的数据,有ai<1000;
  对于50%的数据,有n=1;
  对于60%的数据,有ai<10000;
  对于100%的数据,有ai<100000,n≤5,保证的任何一位不包含0。

思路

对于一开始只有一个数字的情况,如果A能生成B那么A向B连一条边,由于所有生成规则都是可逆的,且代价相同,所以连出的是无向边。BFS出所有能生成的数字,并构图,最后即变成了最小生成树的模型,一开始的数为最小生成树的根,生成树上的边为生成数字的过程。由于图比较稀疏,所以用Kruskal就可以。
对于多个数字的情况,只要一开始在这些数字之间连条权为0的边即可。范围较小,并且图比较一般,不一定要加什么优化。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; 
int n,a[6],bz[100010],r[100010],cnt=0,maxp=1,s=0; 
struct E
{
	int x,y,l; 
}e[500010]; 
bool cmp(E x,E y)
{
	return x.x<y.x;
}
void add(int x,int y,int l)
{
	e[++cnt].x=x,e[cnt].y=y,e[cnt].l=l; 
}
void dfs(int x)
{
	int t=x,t1=0,l=0,c[6],d[6]; 
	while(t>0) c[++l]=t%10,t/=10; 
	for(int i=1; i<l; i++)
		for(int j=i+1; j<=l; j++)
		{
			for(int k=1; k<=l; k++) d[k]=c[k]; 
			d[i]=c[j],d[j]=c[i]; 
			t=0; 
			for(int k=l; k>0; k--) t=t*10+d[k]; 
			if(t==x) continue; 
			add(x,t,(c[i]&c[j])*2+(c[i]^c[j])*2); 
			if(!bz[t]) bz[t]=1,s++,dfs(t); 
		}
	if(l>1)
	{
		for(int i=1; i<=l; i++)
		{
			int p=i+1,q=i-1; 
			if(p>l) p=1; 
			if(q<1) q=l; 
			if(c[i]>=c[p]&&c[i]<=c[q])
			{
				t=0; 
				for(int j=l; j>0; j--) if(j!=i) t=t*10+c[j]; 
				add(x,t,c[i]+(c[p]&c[q])+(c[p]^c[q])); 
				if(!bz[t]) bz[t]=true,s++,dfs(t); 
			}
		}
	}
	if(x*10>=maxp) return; 
	for(int i=c[1]; i<=c[l]; i++)
	{
		t=x*10+i; 
		add(x,t,i+(c[1]&c[l])+(c[1]^c[l])); 
		if(!bz[t]) bz[t]=1,s++,dfs(t); 
		t=i; 
		for(int j=l; j>0; j--) t=t*10+c[j]; 
		add(x,t,i+(c[1]&c[l])+(c[1]^c[l])); 
		if(!bz[t]) bz[t]=1,s++,dfs(t); 
	}
	for(int i=1; i<l; i++)
		for(int j=c[i+1]; j<=c[i]; j++)
		{
			t=0; 
			for(int k=l; k>0; k--) if(k==i) t=(t*10+j)*10+c[k]; else t=t*10+c[k]; 
			add(x,t,j+(c[i+1]&c[i])+(c[i+1]^c[i])); 
			if(!bz[t]) bz[t]=1,s++,dfs(t); 
		}
}

int get(int k)
{
	if(r[k]==k) return k; 
	else 
	{
		r[k]=get(r[k]); 
		return r[k]; 
	}
}
int main()
{
	scanf("%d",&n); 
	for(int  i=1; i<=n; i++)
	{
		scanf("%d",&a[i]); 
		bz[a[i]]=1; s++; 
		for(int  j=1; j<i; j++) add(a[i],a[j],0); 
		while(a[i]>=maxp) maxp*=10; 
	}
	for(int i=1; i<=n; i++) dfs(a[i]); 
	for(int i=1; i<maxp; i++) r[i]=i; 
	int i=1,ans=0; 
	sort(e+1,e+cnt+1,cmp);
	while(s>1)
	{
		int p=get(e[i].x),q=get(e[i].y); 
		if(p!=q)
		{
			ans+=e[i].l; 
			r[p]=q; 
			s--; 
		}
		i++; 
	}
	printf("%d",ans); 
	return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值