第二题:
[编程题] 困兽之斗
经过深思熟虑之后,小贱君打算去M国闯一闯,那是一个古老的东方国度,传说有很多高阶魔法师,他想成为一名伟大的魔法师,将来征服星辰大海。 经过千辛万苦,小贱君终于来到了M国,不幸的是刚进城门小贱君就被M国的守城士兵困在了一种叫做“困兽之斗”的阵法之中。 士兵对小贱君说:“看到漂浮在你身边的宝石了吗?彩虹连接的两颗宝石可以任意交换位置,你需要通过一系列交换后使得宝石组成的字符串的字典序最小。若不能破阵,那还是请回吧!” 小贱君观察了一下周围的宝石,只见每颗宝石上标有一个小写字母,而且有一些宝石上通过彩虹与其他宝石相连。 琢磨了半天,他终于搞懂了这个阵法的意思: 若宝石系列为:dcba 其中有两道彩虹,分别是(0,1),(1,2),代表第一个位置上的宝石可以和第二个位置上的宝石互换,第二个位置上的宝石可以和第三个位置上的宝石互换,最终可以得到字典序最小的宝石系列:bcda。 作为小贱君的死党,你有什么方法帮助他破阵吗?
输入描述:
输入包含多组测试数据。
对于每组测试数据: 字符串s --- 代表宝石序列 n --- 代表有n条彩虹 接下来n行,每行两个数ai,bi --- 表示ai和bi由一条彩虹相连。 保证: 1<=s的长度<=10000 1<=n<=10000 且输入数据均合法。输出描述:
对于每组数据,输出一个字符串
输入例子:
dcba20 11 2hellonowcoder40 11 42 52 3
输出例子:
bcdaehllonowcoder 思路: 并查集 + 排序 把能互相连通的字母,进行排序
1 #include2 #include 3 #include 4 #include 5 #include 6 7 #define N 10005 8 9 using namespace std;10 11 int n;12 char s[N];13 int f[N];14 char ans[N];15 int l;16 17 vector v[N];18 vector pos[N];19 20 int find(int x){21 return x == f[x] ? x : f[x] = find(f[x]);22 }23 24 void merge(int a,int b){25 int fa,fb;26 fa = find(a);27 fb = find(b);28 if(fa == fb) return;29 f[fb] = fa;30 }31 32 void ini(){33 l = strlen(s);34 scanf("%d",&n);35 int i;36 for(i = 0;i < l;i++){37 f[i] = i;38 v[i].clear();39 pos[i].clear();40 }41 int a,b;42 for(i = 1;i <= n;i++){43 scanf("%d%d",&a,&b);44 merge(a,b);45 }46 }47 48 void solve(){49 int i,f;50 for(i = 0;i < l;i++){51 f = find(i);52 pos[f].push_back(i);53 v[f].push_back(s[i]);54 }55 for(i = 0;i < l;i++){56 sort(v[i].begin(),v[i].end());57 }58 for(i = 0;i < l;i++){59 int sz = pos[i].size();60 for(int j = 0;j < sz;j++){61 ans[ pos[i][j] ] = v[i][j];62 }63 }64 ans[l] = '\0';65 }66 67 int main(){68 while(scanf("%s",s)!=EOF){69 ini();70 solve();71 printf("%s\n",ans);72 }73 return 0;74 }
第三题:
[编程题]绝域之门
经过多次强攻之后,赫柏带领的军团不仅没能击败鲁卡斯,反而被鲁卡斯打得七零八落,赫柏终于体会到了高阶天之驱逐者的强大实力。 不过,赫柏最终还是找到了鲁卡斯的致命弱点,他发现鲁卡斯喜欢收集上古卷轴,因为上古卷轴能够让鲁卡斯获得神秘之力。 卢卡斯决定使用上古卷轴将卢卡斯引诱到绝域之门,利用绝域之门的力量消灭卢卡斯。 赫柏注意到卢卡斯喜欢收集不同的卷轴,如果总是捡到相同的上古卷轴,它的兴趣就会逐渐降低。 赫柏现在拥有N种不同的卷轴,每种卷轴有Ai个。现在他要将这N个卷轴分散在鲁卡斯领地到绝域之门的路上,每一种排列方式都有一个吸引值Charm,吸引值越高,鲁卡斯被引诱到绝域之门的概率越高。 Charm=Sum of all D(i),其中D(i)=k-i,i为该排列中卷轴i的下标,k为位于i后面且和i是同一种卷轴的卷轴下标。 现在所有的卷轴以<卷轴名称 数量>的格式给出,你需要输出所有卷轴的排列顺序,使得吸引值最大,如果有多种排列方式满足条件,输出按照名字排列字典序最小的一个。
输入描述:
多组测试数据,请处理到文件结束。 对于每组测试数据: 第一行:一个整数N,代表有N种卷轴。 第二行:N种卷轴的描述。 保证: 0<=N<=50; 卷轴名称为长度1~10的字母,每种卷轴的数量为1~800之间的一个整数。
输出描述:
输出所有卷轴的一个排列。
输入例子:
3Thunder 1 Wind 3 Soil 2
输出例子:
Soil Wind Thunder Wind Soil Wind
题解转自:
每种字符串的吸引值只与它第一次出现和最后一次出现的位置有关,所以我们可以先把所有字符串的首尾出现位置确定,再把其余的字符串塞到中间就行了,安排字符串位置时均按照字典序由小到大的顺序。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 8 #define N 55 9 10 using namespace std;11 12 struct PP{13 string s;14 int count;15 }A[N];16 17 bool cmp(PP a,PP b){18 return a.s < b.s;19 }20 21 int n;22 string ans;23 string l,r,mid;24 25 void ini(){26 ans = l = r = mid = "";27 int i;28 for(i = 0;i < n;i++){29 cin >> A[i].s >> A[i].count;30 }31 }32 33 void solve(){34 sort(A , A + n,cmp);35 int i;36 for(i = 0;i < n;i++){37 if(A[i].count > 1){38 l += A[i].s + ' '; 39 r += A[i].s + ' ';40 A[i].count -= 2;41 }42 }43 for(i = 0;i < n;i++){44 while(A[i].count >= 1){45 mid += A[i].s + ' '; 46 A[i].count --;47 }48 }49 ans = l + mid + r;50 if(ans.size() >= 1){51 ans.pop_back();52 }53 }54 55 int main(){56 while(scanf("%d",&n)!=EOF){57 ini();58 solve();59 cout< <