题目链接
密码依然是fighting!

百练上北大夏令营的机试题目,但是很多都找不到可以提交网站的地方,只看了几个能再Virtual Judge上的题目。感受就是题目很长,代码量也不少,题目也有一定难度,时间也很短。总之就是“南”,这些人太厉害了吧!
大概有三个较为简单的小模拟的题目。也没有找到可以提交的OJ。

题目大意:跳房子的游戏,求一个数字变到另外一个数字最少操作步数。操作H和操作O分别定义如下:

  1. if the stone falls into a house (marked as H), we can jump from the current house i to the house 3*i;

  2. if the stone falls outside the house (marked as O), we can jump from the current house i to house i/2.(round down).
    题目保证操作步数再25步之内。
    题解:上面的条件很重要,使得这个题不考虑贪心和DP,而是BFS最短路的问题,因为深度最多25步,而且这个题需要保存路径,输出字典序最小的操作方案。
    代码是别人写的,找不到提交的地方。

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <map>
  5. #include <queue>
  6. using namespace std;
  7. int n, m;
  8. struct node
  9. {
  10. int index;
  11. int step;
  12. vector<char> s; //记录路径
  13. };
  14. void BFS()
  15. {
  16. map<int, bool> mp;
  17. queue<node> q;
  18. node temp;
  19. temp.index = n;
  20. temp.step = 0;
  21. q.push(temp);
  22. while (!q.empty())
  23. {
  24. node top = q.front();
  25. q.pop();
  26. for (int i = 0; i < 2; i++)
  27. {
  28. node temp = top;
  29. if (i == 0)
  30. {
  31. temp.index = top.index * 3;
  32. temp.step = top.step + 1;
  33. if (!mp[temp.index])
  34. {
  35. temp.s.push_back(\'H\');
  36. q.push(temp);
  37. mp[temp.index] = true;
  38. }
  39. }
  40. else
  41. {
  42. temp.index = top.index / 2;
  43. temp.step = top.step + 1;
  44. if (!mp[temp.index])
  45. {
  46. temp.s.push_back(\'O\');
  47. q.push(temp);
  48. mp[temp.index] = true;
  49. }
  50. }
  51. if (temp.index == m)
  52. {
  53. int len = temp.s.size();
  54. cout << len << endl;
  55. for (int i = 0; i < len; i++)
  56. {
  57. cout << temp.s[i];
  58. }
  59. cout << endl;
  60. return;
  61. }
  62. }
  63. }
  64. }
  65. int main()
  66. {
  67. while (cin >> n >> m)
  68. {
  69. if (n == 0 && m == 0)
  70. {
  71. break;
  72. }
  73. BFS();
  74. }
  75. return 0;
  76. }

题目大意:
一个二叉搜索树,不断删除树的叶子,给出叶子信息,求这个二叉搜索树的先序遍历。
题解:
逆向读取输入信息,也就是从顶向下构建这个二叉搜索树,建树之后先序遍历即可。建树操作还可以更加熟练一下。

  1. #include <iostream>
  2. #include<stdio.h>
  3. #include<string>
  4. #include<algorithm>
  5. #include<cmath>
  6. #include<cstring>
  7. #include<vector>
  8. using namespace std;
  9. const int N=30;
  10. struct node{
  11. char c;
  12. node *l,*r;
  13. node(char c=\'a\',node *l=NULL,node *r=NULL):c(c),l(l),r(r){}
  14. };
  15. node tree[30];
  16. int id;
  17. node *insertTree(node *rt,char val){
  18. if(rt==NULL){
  19. tree[id].c=val;
  20. tree[id].l=NULL;
  21. tree[id].r=NULL;
  22. return &tree[id++];//这里的下标不重要,只需要保存全部结点
  23. }
  24. if(val<rt->c)rt->l=insertTree(rt->l,val);
  25. else rt->r=insertTree(rt->r,val);
  26. return rt;
  27. }
  28. void preOrder(node *rt){
  29. if(rt){
  30. putchar(rt->c);
  31. preOrder(rt->l);
  32. preOrder(rt->r);
  33. }
  34. }
  35. int main()
  36. {
  37. vector<char>ve;
  38. char ch;
  39. while(cin>>ch&&ch!=\'$\'){
  40. ve.clear();
  41. ve.push_back(ch);
  42. while(cin>>ch){
  43. if(ch==\'*\'||ch==\'$\')break;
  44. ve.push_back(ch);
  45. }
  46. node *root=NULL;
  47. id=0;
  48. for(int i=ve.size()-1;i>=0;i--){
  49. root=insertTree(root,ve[i]);
  50. }
  51. preOrder(root);
  52. puts("");
  53. }
  54. return 0;
  55. }

题目大意:
交换物品,不同等级的人有不同的物品交换,交换中需要支付一定的钱。eg:物品A+100=物品B。
限制条件是,在全部交换过程中,最高等级的人和最低等级的人等级差不能超过M。
题解:
原本还以为是DP,结果是我傻了。最短路问题,加上枚举最低等级为minLevel的交换者,那么合法的交换者就是等级为minLevel到minLevel+M之间的人。交换建图,额外付出的钱为路径cost,注意方向性。时空复杂度可过,使用Dijkstra的朴素写法即可。

  1. #include <iostream>
  2. #include<stdio.h>
  3. #include<string>
  4. #include<algorithm>
  5. #include<cmath>
  6. #include<cstring>
  7. using namespace std;
  8. int m,n;
  9. const int N=105;
  10. const int INF=0x3f3f3f3f;
  11. int price[N],level[N];
  12. int edge[N][N];
  13. int vis[N];
  14. int d[N];
  15. void init(){
  16. for(int i=0;i<n;i++){
  17. for(int j=0;j<n;j++){
  18. edge[i][j]=INF;
  19. }
  20. }
  21. for(int i=0;i<n;i++){
  22. cin>>price[i]>>level[i];
  23. level[i]--;//0开始
  24. int x;
  25. cin>>x;
  26. for(int j=0;j<x;j++){
  27. int v,p;
  28. cin>>v>>p;
  29. v--;
  30. edge[v][i]=p;//v到i的价格为p
  31. }
  32. }
  33. }
  34. int dijkstr(){
  35. for(int i=0;i<n;i++)d[i]=price[i];//把起点当作超级源点
  36. for(int i=0;i<n;i++){
  37. int temp=INF;
  38. int x;//最小点
  39. for(int j=0;j<n;j++)
  40. if(vis[j]&&d[j]<=temp)
  41. temp=d[x=j];
  42. vis[x]=0;//不再走
  43. for(int j=0;j<n;j++)
  44. if(d[x]+edge[x][j]<d[j]&&vis[j])
  45. d[j]=d[x]+edge[x][j];
  46. }
  47. return d[0];//0
  48. }
  49. int main()
  50. {
  51. cin>>m>>n;
  52. init();
  53. int ans=INF;
  54. for(int i=0;i<n;i++){
  55. int minLevel=level[i];//最小
  56. for(int j=0;j<n;j++){
  57. if(level[j]-minLevel>m||minLevel>level[j])
  58. vis[j]=0;//不可
  59. else vis[j]=1;
  60. }
  61. int cur=dijkstr();
  62. // cout<<cur<<endl;
  63. ans=min(ans,cur);
  64. }
  65. cout<<ans<<endl;
  66. return 0;
  67. }

原本还有两个题,一个题目太长了,看不下去了,一个大模拟的题,我就放弃了。。。

版权声明:本文为gzr2018原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/gzr2018/p/12304148.html