前言
你可能需要:
- 最小生成树
- 有一定的调试能力(doge
题目
问题描述
一个数 可以按以下规则生成数字:
- 将任意两位交换,若交换的数字为
和
,生成的代价为
。例如
可以生成
,因为
可以从
的个位(
)与百位(
)交换后得到,代价为
。
- 将其中一位数删除,但是删除的数要满足大等于它左边的数,且小等于它右边的数,并且定义最高位左边的数为个位,个位右边的数为最高位。若删除的数字为
,它左边的数为
,它右边的数为
,则生成的代价为
。例如
,可以删除个位的数得到
,但是因为
,所以
是不能被删除的。特别地,若
为两位数,它能删除当且仅当
的两位数相同,若
为一位数,它是不能被删除的。
- 在两位数字之间,也可以是数字的前面或后面加入一位数,同样地,加入的数要满足大等于它左边的数,且小等于它右边的数,并且定义最高位左边的数为个位,个位右边的数为最高位。若加入的数字为
,它左边的数为
,它右边的数为 cc ,则生成的代价为 \text{a+(b & c)+(b ^ c)} 。例如
,它可以在 22 与 44 之间加入一个 33 ,生成 23412341 ,也可以在数的末尾加入一个 11 或者 22 ,当然还有其它可以生成的数,但是不能在 44 和 11 之间加入数字。
你的任务是, 一开始为
个不同的给定数组成的集合,每次可以从
中取出一个数生成一个满足生成规则的数加入
中,并且取出的数仍然存在于
中。生成的数的位数不能大于
初始集合最大的数的位数。问在
元素最多的情况下,总代价最小是多少。
输入格式
输入的第 行为一个正整数
,为集合
初始元素个数。
第 行包含
个正整数
,数之间空格隔开,为
中初始元素。
输出格式
输出包括一个正整数,为最小代价。
样例输入1
2
111 22
样例输出1
12
样例1解释
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。
数据范围及约定
对于 的数据,有
;
对于 的数据,有
;
对于 的数据,有
;
对于 的数据,有
;
对于 的数据,有
,
,保证的任何一位不包含
。
分析
是吧,直接暴力算出有哪些状态就完事了。
然后暴力建图从哪个状态推入哪个状态,形成一个生成图。
最后直接最小生成树求权和,搞定。
注意:收录简单,代码超标。
code
#include<bits/stdc++.h>
#define int ll
typedef long long ll;
using namespace std;
const int MAXN=6;
struct Node{
int u,v,w;
Node(){}
Node(int a,int b,int c):u(a),v(b),w(c){}
bool operator<(const Node &b){
return w<b.w;
}
};
vector<Node>ege;
unordered_set<int>vis;
unordered_map<int,int>gid;
int wcnt,tot,maxw,n,a[MAXN+1];
int Getwei(int vv){
int cnt=0;
while(vv){
cnt++;
vv/=10;
}
return cnt;
}
//vector<pair<int,int> >G[(int)1e5+1];
int nxt(int qwq){return (qwq==wcnt?1:qwq+1);}
int pre(int qwq){return (qwq==1?wcnt:qwq-1);}
int change_value(int a,int b){return ((a&b)+(a^b))*2;}
int delete_value(int a,int b,int c){return a+(b&c)+(b^c);}
int insert_value(int a,int b,int c){return a+(b&c)+(b^c);}
void BFS(int beg){
if(vis.count(beg))return;
// cout<<"$$$$$$$$$$$$$\n";
vis.insert(beg);
gid[beg]=++tot;
queue<int>Q;
Q.push(beg);
while(!Q.empty()){
int b[7]={};
wcnt=0;
int tmp=Q.front(),F=Q.front();Q.pop();
while(tmp){
b[++wcnt]=tmp%10;
tmp/=10;
}
reverse(b+1,b+1+wcnt);
// for(int i=1;i<=wcnt;i++)cout<<b[i];
// cout<<"^^^^^^^^^^^^^"<<F<<"^^^^^^^\n";
//////////////转移操作1////////////////
for(int i=1;i<=wcnt;i++){
for(int j=i+1;j<=wcnt;j++){
swap(b[i],b[j]);
int to=0;
for(int k=1;k<=wcnt;k++)to=10*to+b[k];
if(F==to)continue;
if(!vis.count(to)){
gid[to]=++tot;
Q.push(to);
vis.insert(to);
// cout<<to<<"###\n";
}
// G[gid[F]].push_back(make_pair(gid[to],change_value(b[i],b[j])));
ege.push_back((Node){gid[F],gid[to],change_value(b[i],b[j])});
swap(b[i],b[j]);
}
}
//////////////转移操作2////////////////
if(wcnt!=1){
for(int i=1;i<=wcnt;i++){
if(b[i]<b[pre(i)]||b[i]>b[nxt(i)])continue;
int to=0;
for(int k=1;k<=wcnt;k++){
if(k==i)continue;
to=10*to+b[k];
}
if(!vis.count(to)){
gid[to]=++tot;
Q.push(to);
vis.insert(to);
// cout<<to<<"&&&&\n";
}
// G[gid[F]].push_back(make_pair(gid[to],delete_value(b[i],b[pre(i)],b[nxt(i)])));
ege.push_back((Node){gid[F],gid[to],delete_value(b[i],b[pre(i)],b[nxt(i)])});
}
}
//////////////转移操作3////////////////
if(wcnt<maxw){
for(int ins=b[wcnt];ins<=b[1];ins++){
int to=ins;
for(int j=1;j<=wcnt;j++)to=10*to+b[j];
if(!vis.count(to)){
gid[to]=++tot;
Q.push(to);
vis.insert(to);
// cout<<to<<"!!!!!\n";
}
// G[gid[F]].push_back(make_pair(gid[to],insert_value(ins,b[wcnt],b[1])));
ege.push_back((Node){gid[F],gid[to],insert_value(ins,b[wcnt],b[1])});
}
for(int i=1;i<=wcnt;i++){
for(int ins=b[i];ins<=b[nxt(i)];ins++){
int to=0;
for(int k=1;k<=i;k++)to=10*to+b[k];
to=10*to+ins;
for(int k=i+1;k<=wcnt;k++)to=10*to+b[k];
if(!vis.count(to)){
gid[to]=++tot;
Q.push(to);
vis.insert(to);
// cout<<to<<' '<<i<<' '<<ins<<"!!!\n";
}
// G[gid[F]].push_back(make_pair(gid[to],insert_value(ins,b[i],b[nxt(i)])));
ege.push_back((Node){gid[F],gid[to],insert_value(ins,b[i],b[nxt(i)])});
}
}
}
}
return;
}
//int dist[(int)1e5+1][MAXN+1];
//void dijkstra(int beg,int id){
// priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >Q;
// Q.push(make_pair(0,beg));
// dist[beg][id]=0;
// while(!Q.empty()){
// auto F=Q.top();Q.pop();
// if(F.first>dist[F.second][id])continue;
// int from=F.second;
// for(auto i:G[from]){
// int to=i.first,w=i.second;
// if(dist[to][id]>dist[from][id]+w){
// dist[to][id]=dist[from][id]+w;
// Q.push(make_pair(dist[to][id],to));
// }
// }
// }
// return;
//}
int fa[(int)1e5+1];
int GetFather(int x){
if(fa[x]==0)return x;
return fa[x]=GetFather(fa[x]);
}
signed main(){
freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",a+i);
// cout<<Getwei(a[i])<<"$$$\n";
maxw=max(maxw,Getwei(a[i]));
}
for(int i=1;i<=n;i++)BFS(a[i]);
// cout<<gid[0]<<"###\n";
// for(auto i:gid)printf("%lld %lld\n",i.first,i.second);
// for(auto i:vis){
// printf("this point is:%lld,its gid is %lld\n",i,gid[i]);
// for(auto [to,w]:G[gid[i]])printf("%lld can go to the %lld,weight is %lld\n",i,to,w);
// }
// memset(dist,0x3f,sizeof dist);
vis.clear();
for(int i=1;i<=n;i++)vis.insert(gid[a[i]]);
// BFS2();
sort(ege.begin(),ege.end());
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
int fai=GetFather(gid[a[i]]),faj=GetFather(gid[a[j]]);
if(fai==faj)continue;
fa[fai]=faj;
}
}
int ans=0;
for(auto i:ege){
if(GetFather(i.u)==GetFather(i.v))continue;
ans+=i.w;
fa[GetFather(i.u)]=GetFather(i.v);
}
// for(int i=1;i<=n;i++)dijkstra(gid[a[i]],i);
// int ans=0;
// for(int i=1;i<=tot;i++){
// int minn=LLONG_MAX;
// for(int j=1;j<=n;j++)minn=min(minn,dist[i][j]);
// ans+=minn;
// cout<<i<<' '<<minn<<"**********\n";
// }
printf("%lld\n",ans);
return 0;
}
1344

被折叠的 条评论
为什么被折叠?



