【MST+BFS】教主的难题

【题目描述】

        一个数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元素最多的情况下,总代价最小是多少。

【输入格式】

      输入的第1行为一个正整数n,为集合S初始元素个数。

  第2行包含n个正整数a1,a2, ..., an,数之间空格隔开,为S中初始元素。

【输入样例】                                                    【输出格式】

2                                                                                                       12
111 22

因为要求元素最大时的最小代价,即用元素数-1次转化得到所有元素的最小代价,是一道明显的MST问题。

Prim算法可以在BFS的同时进行,答案统计比较简单。

初始化最开始的几个元素转化代价为0.

#include
#include
#include
#include
#include
#include
#include
using namespace std;
int n,d[100005],x,maxx,ans;
bool vis[100005];
struct que
{
	int x,d;
	friend bool operator <(const que &a,const que &b)
	{
		return a.d>b.d;
	}
};
priority_queue q;
void bfs(int x,int op)
{
	if(op==0)
	{
		vector a;
		while(x)
		{
			a.push_back(x%10);
			x/=10;
		}
		int l=a.size();
		for(int i=0;i=0;k--)
				{
					y=y*10+a[k];
				}
				swap(a[i],a[j]);
				if(vis[y]) continue;
				if(d[y]>((a[i]&a[j])+(a[i]^a[j]))*2)
				{
					d[y]=((a[i]&a[j])+(a[i]^a[j]))*2;
					q.push((que){y,d[y]});
//					cout<maxx) return;
		vector a;
		while(x)
		{
			a.push_back(x%10);
			x/=10;
		}
		int l=a.size();
		for(int i=0;i=a[i+1])
			{
				int y=0;
				for(int j=l-1;j>=i+1;j--)
				{
					y=y*10+a[j];
				}
				for(int j=a[i+1];j<=a[i];j++)
				{
					int sy=y*10+j;
					for(int k=i;k>=0;k--)
					{
						sy=sy*10+a[k];
					}
					if(vis[sy]) continue;
					if(d[sy]>j+(a[i]&a[i+1])+(a[i]^a[i+1]))
					{
						d[sy]=j+(a[i]&a[i+1])+(a[i]^a[i+1]);
						q.push((que){sy,d[sy]});
//						cout<=a[0])
		{
			int y=0;
			for(int i=l-1;i>=0;i--)
			{
				y=y*10+a[i];
			}
			for(int j=a[0];j<=a[l-1];j++)
			{
				int sy=y*10+j;
				if(vis[sy]) continue;
				if(d[sy]>j+(a[0]&a[l-1])+(a[0]^a[l-1]))
				{
					d[sy]=j+(a[0]&a[l-1])+(a[0]^a[l-1]);
					q.push((que){sy,d[sy]});
//					cout<j+(a[0]&a[l-1])+(a[0]^a[l-1]))
				{
					d[sy]=j+(a[0]&a[l-1])+(a[0]^a[l-1]);
					q.push((que){sy,d[sy]});
//					cout< a;
		while(x)
		{
			a.push_back(x%10);
			x/=10;
		}
		int l=a.size();
		for(int i=1;i=a[i+1]&&a[i]<=a[i-1])
			{
				int y=0;
				for(int k=l-1;k>=i+1;k--)
				{
					y=y*10+a[k];
				}
				for(int k=i-1;k>=0;k--)
				{
					y=y*10+a[k];
				}
				if(vis[y]) continue;
				if(d[y]>a[i]+(a[i-1]&a[i+1])+(a[i-1]^a[i+1]))
				{
					d[y]=a[i]+(a[i-1]&a[i+1])+(a[i-1]^a[i+1]);
					q.push((que){y,d[y]});
				}
			}
		}
		if(a[0]>=a[1]&&a[0]<=a[l-1])
		{
			int y=0;
			bool flag=0;
			for(int k=l-1;k>=1;k--)
			{
				y=y*10+a[k];
			}
			if(vis[y]) flag=1;
			if(!flag)
			if(d[y]>a[0]+(a[1]&a[l-1])+(a[1]^a[l-1]))
			{
				d[y]=a[0]+(a[1]&a[l-1])+(a[1]^a[l-1]);
				q.push((que){y,d[y]});
			}
		}
		if(a[l-1]>=a[0]&&a[l-1]<=a[l-2])
		{
			int y=0;
			bool flag=0;
			for(int k=l-2;k>=0;k--)
			{
				y=y*10+a[k];
			}
			if(vis[y]) flag=1;
			if(!flag)
			if(d[y]>a[l-1]+(a[0]&a[l-2])+(a[0]^a[l-2]))
			{
				d[y]=a[l-1]+(a[0]&a[l-2])+(a[0]^a[l-2]);
				q.push((que){y,d[y]});
			}
		}
	}
}
int main()
{
	scanf("%d",&n);
	memset(d,0x3f,sizeof(d));
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		q.push((que){x,0});
		maxx=max((int)log10(x)+1,maxx);
	}
	while(!q.empty())
	{
		que u=q.top();
		q.pop();
		if(vis[u.x]) continue;
//		cout<

你可能感兴趣的:(BFS,MST,BFS,MST)