埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 C序列变换

链接:https://www.nowcoder.com/acm/contest/91/C
来源:牛客网
没有账号的同学这样注册,支持博主

题目描述

给定两个长度为n的序列,ai, bi(1<=i<=n), 通过3种魔法使得序列a变换为序列b,也就是ai=bi(1<=i<=n).

魔法1: 交换ai和aj,i!=j

首先通过若干次的魔法1将序列a变换成序列c

魔法2: 对1个数乘2或者加1

魔法3: 对1个数除以2或者减1,如果是奇数,则不能除以2

若ci>bi, 则只能对ci实施魔法3,若ci<bi, 则只能对ci实施魔法2. 例如ci=6, bi=4,

则可以通过对ci实施2次减1操作(魔法3)将ci变为bi, 但不可以对ci除以2再加1将ci变为bi,因为ci>bi, 所以不能对ci实施加1操作(魔法2).

小埃想通过最少的操作次数使得序列a变成序列b, 操作次数是指使用的魔法次数。

输入描述:

输入测试组数T,每组数据,第一行输入n,1<=n<=9,紧接着输入两行,每行n个整数,前一行为a1,a2,…,an,后一行为b1,b2,…,bn.其中1<=ai,bi<=108,1<=i<=n.

输出描述:

每组数据输出一个整数,表示最少的操作次数
示例1

输入

复制
2
2
8 7
5 1
4
4 3 1 3
1 1 4 3

输出

复制
6
3



分析题目,三种操作中,2和3是一样的,1就是交换。
由于N很小很小,可以枚举每种交换的情况。枚举方式:全排列,循环一遍统计生成当前排列所需的交换数。

问题就在于如何求出a[i]通过2或3操作变成b[j]的方案数。
从较大的数向较小的数推,贪心即可求!!!!!具体见代码的calc函数。
这部分需要预处理,如果不预处理的话复杂度加一个log就过不了了。

 1 /*
 2 ◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
 3 ◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇
 4 ◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇
 5 ◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇
 6 ◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◆◆◆◇◇◇◇◇
 7 ◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇
 8 ◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◇◆◆◇◇◇◇◇
 9 ◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
10 ◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
11 ◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◆◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
12 ◇◇◇◇◇◇◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◆◆◆◇◆◆◆◇◇◇◇
13 ◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
14 ◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
15 ◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
16 ◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
17 */
18 #include<iostream>
19 #include<cstdio>
20 #include<cstring>
21 #include<ctime>
22 #include<cstdlib>
23 #include<algorithm>
24 #include<cmath>
25 #include<string>
26 using namespace std;
27 int read(){
28     int xx=0,ff=1;char ch=getchar();
29     while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
30     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
31     return xx*ff;
32 }
33 int N,a[10],b[10],c[10],t[10],lin[10],cost[10][10];
34 int calc(int x,int y){
35     if(x<y)
36         swap(x,y);
37     int re=0;
38     while(x!=y){
39         if(x%2==0){
40             if(x/2>=y)
41                 x/=2,re++;
42             else
43                 re+=x-y,x=y;
44         }
45         else
46             x--,re++;
47     }
48     return re;
49 }
50 int main(){
51     //freopen("in.txt","r",stdin);
52     for(int T=read();T;T--){
53         N=read();
54         for(int i=1;i<=N;i++)
55             a[i]=read();
56         for(int i=1;i<=N;i++)
57             b[i]=read();
58         for(int i=1;i<=N;i++)
59             c[i]=i;
60         for(int i=1;i<=N;i++)
61             for(int j=1;j<=N;j++)
62                 cost[i][j]=calc(a[i],b[j]);
63         /*for(int i=1;i<=N;i++){
64             for(int j=1;j<=N;j++)
65                 printf("%d ",cost[i][j]);
66             puts("");
67         }*/
68         int ans=(1LL<<31)-1,now;
69         do{
70             now=0;
71             for(int i=1;i<=N;i++)
72                 t[i]=c[i],lin[t[i]]=i;
73             for(int i=1;i<=N;i++)
74                 if(t[i]!=i){
75                     int j=lin[i];
76                     swap(t[i],t[j]);
77                     lin[t[i]]=i;
78                     lin[t[j]]=j;
79                     now++;
80                 }
81             for(int i=1;i<=N;i++)
82                 now+=cost[c[i]][i];
83             if(now<ans)
84                 ans=now;
85         }while(next_permutation(c+1,c+1+N));
86         printf("%d\n",ans);
87     }
88     return 0;
89 }
View Code







猜你喜欢

转载自www.cnblogs.com/lzhAFO/p/9119575.html