CoFun 1616 数字游戏

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 Format

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

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

Output Format

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

 

思路:如果a能生成b,那么b也可以生成a,首先我们从n个数里面bfs去生成其他数字,将代价建为边,由于要求最小的生成所有数的代价,因此很容易想到最小生成树,建一个0节点,对初始n个数字建边,边权为0,做最小生成树即可。

  1 #include<algorithm>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 #define ll long long
  7 struct edge{
  8     int u,v,w;
  9 }e[200005];
 10 int vis[1000005],c[1000005],b[1000005],n,tot,fa[200005],mx,h,t;
 11 bool cmp(edge a,edge b){
 12     return a.w<b.w;
 13 }
 14 int find(int x){
 15     if (fa[x]==x) return x;
 16     else return (fa[x]=find(fa[x]));
 17 }
 18 void MST(){
 19     for (int i=1;i<=n;i++){
 20         e[++tot].u=0;
 21         e[++tot].v=c[i];
 22         e[++tot].w=0;
 23     }
 24     std::sort(e+1,e+1+tot,cmp);
 25     for (int i=0;i<=100000;i++) fa[i]=i;
 26     ll ans=0;
 27     for (int i=1;i<=tot;i++){
 28         int p=find(e[i].u),q=find(e[i].v);
 29         if (p==q) continue;
 30         fa[p]=q;
 31         ans+=(ll)e[i].w;
 32     }
 33     printf("%lld\n",ans);
 34 }
 35 int query(int x){
 36     int cnt=0;
 37     while (x){
 38         x/=10;cnt++;
 39     }
 40     return cnt;
 41 }
 42 void work(int x){
 43     int T=0,Len=0,y=x;
 44     while (y){
 45        b[Len++]=y%10;
 46        y/=10;
 47     }
 48     
 49     for (int i=0;i<Len;i++)
 50      for (int j=i+1;j<Len;j++){
 51             std::swap(b[i],b[j]);
 52             int cost=((b[i]&b[j])+(b[i]^b[j]))*2;
 53             T=0;
 54             for (int k=Len-1;k>=0;k--)
 55              T=T*10+b[k];
 56             if (T==x||query(T)>mx) continue; 
 57             if (!vis[T]) vis[T]=1,c[++t]=T; 
 58             e[++tot].u=x;e[tot].v=T;e[tot].w=cost;
 59             std::swap(b[i],b[j]);
 60     }
 61     if (Len>2){
 62      for (int i=0;i<Len;i++){
 63         int L=b[(i+1)%Len],R=b[(i-1+Len)%Len];
 64         if (b[i]<L||b[i]>R) continue;
 65         int cost=b[i]+(L^R)+(L&R);
 66         T=0;
 67         for (int j=Len-1;j>=0;j--)
 68          if (j!=i)
 69           T=T*10+b[j];
 70         if (query(T)>mx) continue;  
 71         e[++tot].u=x,e[tot].v=T,e[tot].w=cost;
 72         if (!vis[T]) vis[T]=1,c[++t]=T;  
 73      }
 74     }else
 75     if (Len==2){
 76         if (b[0]==b[1]){
 77             T=b[0];
 78             if (query(T)<=mx){
 79                if (!vis[T]) vis[T]=1,c[++t]=T;
 80                int cost=b[0]+(b[0]^b[1])+(b[0]&b[1]);
 81                e[++tot].u=x;e[tot].v=T;e[tot].w=cost;
 82             }
 83         }
 84     }
 85     for (int i=0;i<Len;i++){
 86         int L=b[(i+1)%Len],R=b[(i+Len)%Len];
 87         for (int j=L;j<=R;j++){
 88             T=0;
 89             for (int k=Len-1;k>=0;k--)
 90              if (k==i)
 91               T=T*10+j,T=T*10+b[k];
 92              else 
 93               T=T*10+b[k];
 94             if (query(T)>mx) break;
 95             if (!vis[T]) vis[T]=1,c[++t]=T;
 96             int cost=T+(L^R)+(L&R);
 97             e[++tot].u=x;e[tot].v=T;e[tot].w=cost; 
 98         }
 99     }
100     int L=b[0],R=b[Len-1];
101     for (int j=L;j<=R;j++){
102         T=0;
103         for (int k=Len-1;k>=0;k--)
104          T=T*10+b[k];
105         T=T*10+j;
106         if (query(T)>mx) break;
107         if (!vis[T]) vis[T]=1,c[++t]=T;
108         int cost=T+(L^R)+(L&R);
109         e[++tot].u=x;e[tot].v=T;e[tot].w=cost; 
110     }
111 }
112 int main(){
113     scanf("%d",&n);
114     for (int i=1;i<=n;i++){
115         scanf("%d",&c[i]);
116         int T=c[i],cnt=0;
117         while (T){
118             cnt++;T/=10;
119         }
120         mx=std::max(mx,cnt);
121         vis[c[i]]=1;
122     }
123     h=1,t=n;
124     while (h<=t){
125         int now=c[h++];
126         work(now);
127     }
128     for (int i=1;i<=t;i++)
129      printf("%d\n",c[i]);
130     MST();
131 }

 

posted @ 2016-06-02 17:28  GFY  阅读(571)  评论(0编辑  收藏  举报