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 }
时间: 2024-11-29 07:23:57

CoFun 1616 数字游戏的相关文章

Vijos P1218 数字游戏

描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k.游戏的要求是使你所得的k最大或者最小. 格式 输入格式 输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9).以下n行每行有个整数,其绝对值不大于10^410?4??,按顺序给出圈中的数字,首尾相接. 输出

JavaScript一个猜数字游戏

效果图: 代码: <body> <script type="text/javascript"> window.onload = newgame; //页面载入的时候就开始一个新的游戏 window.onpopstate = popState; //处理历史记录相关事件 var state,ui; //全局变量,在newgame()方法中会对其初始化 function newgame( playagin ){ //开始一个新的猜数字游戏 //初始化一个包含需要的文

BZOJ2900 好玩的数字游戏

好玩的数字游戏 TK在虐题的同时,也喜欢玩游戏.现在,有这样的一个游戏,规则是这样的:先随机给出一个数字N,然后你在操场上把1到N的所有数字写成一排,就像这样:123456789101112131415-.接着你在每个数字前面添上加减号,每逢排在奇数位上的数字,就写上加号:每逢排在偶数位上的数字,就写上减号.恩-最后你得到一个超级长的式子.并且可以算出这个式子的结果.TK觉得这个游戏很有意思,于是他没日没夜地玩啊玩啊玩啊-或许你觉得这个游戏没有意思-恩-但是,如果你是TK,对于给定的N,你能够算

猜数字游戏及rand()函数

#include<stdio.h>#include<stdlib.h>int main() { short number; short guess=0; number=rand()%100; number++; printf("猜数字游戏\n"); printf("该数字在1到100之间\n"); while(guess!=number) { printf("请你输入所猜数字:"); scanf("%hd&quo

DP——数字游戏

Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k.游戏的要求是使你所得的k最大或者最小. 例如,对于下面这圈数字(n=4,m=2): 当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4

原创Android游戏--猜数字游戏V1.1 --数据存储,Intent,SimpleAdapter的学习与应用

--------------------------------------------------------------- V0.1版本 上次做完第一个版本后,发现还有一些漏洞,并且还有一些可以添加的功能,以及一些可改进的地方,于是准备继续完善此游戏,顺便学Android了. 本次更新信息如下: 1.改正了随机数生成算法,更正了不能产生数字'9'的bug 2.增加了数据存储与IO的内容,使用了SharedPreferences保存数据 3.保存数据为: 总盘数,猜中的盘数 4.使用了Simp

*循环-20. 猜数字游戏

1 /* 2 * Main.c 3 * C20-循环-20. 猜数字游戏 4 * Created on: 2014年8月18日 5 * Author: Boomkeeper 6 *********测试部分通过********* 7 */ 8 9 #include <stdio.h> 10 11 int main(void){ 12 13 int random = 0,N = 0;//系统输入的随机数和最大猜测次数 14 int in = 0;//每次输入的猜测 15 int count = 0

XDU1160 - 科协的数字游戏I

Description 科协里最近很流行数字游戏.某人命名了一种不降数,这种数字必须满足从左到右各位数字成大于等于的关系,如123,446.现在大家决定玩一个游戏,指定一个整数闭区间[a,b],问这个区间内有多少个不降数. Input 题目有多组测试数据.每组只含2个数字a, b (1 <= a, b <= 2^31). Output 每行给出一个测试数据的答案,即[a, b]之间有多少阶梯数. Sample Input 1 9 1 19 Sample Output 918 数位DP基础题:

1861 奶牛的数字游戏 2006年USACO

codevs——1861 奶牛的数字游戏 2006年USACO 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题解 题目描述 Description 奶牛们又在玩一种无聊的数字游戏.输得很郁闷的贝茜想请你写个程序来帮她在开局时预测结果.在游戏的开始,每头牛都会得到一个数N(1<=N<=1,000,000).此时奶牛们的分数均为0.如果N是奇数,那么奶牛就会把它乘以3后再加1.如果N是偶数,那么这个数就会被除以2.数字每变动一次,这头奶牛就得到1分.当N的