当前位置:   article > 正文

PTA数据结构11——15_某天,诺诺有许多活动需要参加。但由于活动太多,诺诺无法参加全部活动。请帮诺诺安

某天,诺诺有许多活动需要参加。但由于活动太多,诺诺无法参加全部活动。请帮诺诺安

7-11 最少失约

某天,诺诺有许多活动需要参加。但由于活动太多,诺诺无法参加全部活动。请帮诺诺安排,以便尽可能多地参加活动,减少失约的次数。假设:在某一活动结束的瞬间就可以立即参加另一个活动。

输入格式:

首先输入一个整数T,表示测试数据的组数,然后是T组测试数据。每组测试数据首先输入一个正整数n,代表当天需要参加的活动总数,接着输入n行,每行包含两个整数i和j(0≤i<j<24),分别代表一个活动的起止时间。

输出格式:

对于每组测试,在一行上输出最少的失约总数。

输入样例:

  1. 1
  2. 5
  3. 1 4
  4. 3 5
  5. 3 8
  6. 5 9
  7. 12 14

输出样例:

2
  1. #include<stdio.h>
  2. //结构体
  3. struct ss{
  4. int a;
  5. int b;
  6. }p[];
  7. //结构体
  8. //冒泡排序
  9. void bubble(struct ss arr[], int len)
  10. {
  11. for (int i = 0; i < len - 1; i++)//9趟
  12. {
  13. int flag = 0;
  14. for (int j = 0; j < len - 1 - i; j++)//比较9次
  15. {
  16. if (arr[j].b>arr[j + 1].b)
  17. {
  18. flag = 1;
  19. int temp = arr[j].a;
  20. arr[j].a = arr[j + 1].a;
  21. arr[j + 1].a = temp;
  22. temp = arr[j].b;
  23. arr[j].b = arr[j + 1].b;
  24. arr[j + 1].b = temp;
  25. }
  26. }
  27. if (!flag)
  28. break;
  29. }
  30. }
  31. //冒泡排序
  32. int main()
  33. {
  34. int T, n;
  35. scanf("%d",&T);//输入测试组数
  36. for(int w = 0; w < T; w ++)
  37. {
  38. scanf("%d",&n);//输入n组测试数据
  39. for(int j = 0; j < n; j ++){
  40. scanf("%d %d",&(p[j].a), &(p[j].b) );//活动起止时间
  41. }
  42. bubble(p,n);//引用冒泡排序
  43. int j = 0;
  44. int count = 1;//因为第一个默认是直接参加
  45. for(int i = 1; i < n; i ++){
  46. if(p[i].a >= p[j].b){
  47. j = i;
  48. count ++;
  49. }
  50. }
  51. printf("%d\n",n-count);
  52. }
  53. }

7-12 n皇后问题

要求在n*n格的棋盘上放置彼此不会相互攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

输入格式:

测试数据有多组,处理到文件尾。对于每组测试,输入棋盘的大小n(1<n<12)。

输出格式:

对于每组测试,输出满足要求的方案个数。

输入样例:

4

输出样例:

2
  1. #include<stdio.h>
  2. #include<string.h>
  3. #define N 30
  4. int col[N],dg[N],udg[N];
  5. int n,ans;
  6. void dfs(int u)
  7. {
  8. int i=0;
  9. if(u==n)
  10. {
  11. ans++;
  12. return ;
  13. }
  14. for(i=0;i<n;i++)
  15. {
  16. if(!col[i]&&!dg[i+u]&&!udg[i-u+n])
  17. {
  18. col[i]=dg[i+u]=udg[i-u+n]=1;
  19. dfs(u+1);
  20. col[i]=dg[i+u]=udg[i-u+n]=0;
  21. }
  22. }
  23. }
  24. void print()
  25. {
  26. int i=0;
  27. for(i=0;i<n;i++)
  28. printf("%d %d %d\n",col[i],dg[i],udg[i]);
  29. printf("\n");
  30. }
  31. int main()
  32. {
  33. int i=0;
  34. while(~scanf("%d",&n))
  35. {
  36. // print();
  37. ans=0;
  38. dfs(0);
  39. printf("%d\n",ans);
  40. // print();
  41. }
  42. return 0;
  43. }

7-13 最佳组队问题

双人混合ACM程序设计竞赛即将开始,因为是双人混合赛,故每支队伍必须由1男1女组成。现在需要对n名男队员和n名女队员进行配对。由于不同队员之间的配合优势不一样,因此,如何组队成了大问题。
给定n×n优势矩阵P,其中P[i][j]表示男队员i和女队员j进行组队的竞赛优势(0<P[i][j]<10000)。设计一个算法,计算男女队员最佳配对法,使组合出的n支队伍的竞赛优势总和达到最大。

输入格式:

测试数据有多组,处理到文件尾。每组测试数据首先输入1个正整数n(1≤n≤9),接下来输入n行,每行n个数,分别代表优势矩阵P的各个元素。

输出格式:

对于每组测试,在一行上输出n支队伍的竞赛优势总和的最大值。

输入样例:

  1. 3
  2. 10 2 3
  3. 2 3 4
  4. 3 4 5

输出样例:

18
  1. #include<stdio.h>
  2. #include<string.h>
  3. #define N 10
  4. int p[N][N];
  5. int n,ans,res;
  6. int flag[N];
  7. int a[N];
  8. void dfs(int u)
  9. {
  10. int i=0;
  11. if(u==n+1)
  12. {
  13. res=0;
  14. for(i=1;i<=n;i++)
  15. res+=a[i];
  16. if(ans<res)
  17. ans=res;
  18. return ;
  19. }
  20. for(i=1;i<=n;i++)
  21. {
  22. if(!flag[i])
  23. {
  24. flag[i]=1;
  25. a[u]=p[u][i];
  26. dfs(u+1);
  27. flag[i]=0;
  28. }
  29. }
  30. }
  31. int main()
  32. {
  33. int i=0,j=0;
  34. while(~scanf("%d",&n))
  35. {
  36. for(i=1;i<=n;i++)
  37. for(j=1;j<=n;j++)
  38. scanf("%d",&p[i][j]);
  39. ans=0;
  40. dfs(1);
  41. printf("%d\n",ans);
  42. }
  43. return 0;
  44. }

7-14 猜对了一半(*)

赛场内 n (0<n≤10) 名短跑运动员正在参加百米短跑比赛。赛场外有 m (0<m≤100) 名热心观众,他们每人都对比赛结果作出了 2 个预测。比赛结束后,运动员的名次各不相同,但令人惊奇的是每位观众都猜对了一半。请问这些运动员取得的实际名次是多少?

例如场内有 4 名运动员参加比赛,场外 3 名观众的预测分别为:

  • 1 号运动员名次为 1,2 号运动员名次为 3
  • 3 号运动员名次为 1,4 号运动员名次为 4
  • 4 号运动员名次为 2,1 号运动员名次为 3

由每人猜对一半推理可知:

  • 1 号运动员名次为 4
  • 2 号运动员名次为 3
  • 3 号运动员名次为 1
  • 4 号运动员名次为 2

请编写程序,根据观众的预测来推算运动员的实际名次。

输入格式

两个正整数 n 和 m (运动员人数、观众人数)
随后有 m 行数据,每行包含 4 个整数,为 m 位观众的预测
每行包含的 4 个整数 x1​、r1​ 和 x2​、r2​ 表示该观众的两个预测:
x1​ 号运动员名次为 r1​,x2​ 号运动员名次为 r2​

说明:

  • n 名运行员的编号为从 1 到 n 的正整数,无重号和跳号。
  • n 名运动员的名次为从 1 到 n 的正整数,无并列的情况。

输出格式

若问题无解,则输出 None。
若问题有解,则输出多行数据,每一行表示一个答案,按字典序输出。
每一行包含 n 个整数,分别是 1 ~ n 号运动员取得的实际名次。

注:整数间用空格间隔,行末没有空格。

说明:

输入样例1

  1. 4 3
  2. 1 1 2 3
  3. 3 1 4 4
  4. 4 2 1 3

输出样例1

4 3 1 2

输入样例2

  1. 4 3
  2. 3 4 2 1
  3. 4 3 3 2
  4. 1 4 2 3

输出样例2

None

输入样例3

  1. 4 3
  2. 2 4 4 1
  3. 4 2 2 3
  4. 3 4 1 1

输出样例3

  1. 1 4 3 2
  2. 2 3 4 1
  1. #include<stdio.h>
  2. /*n运动员人数,m观众人数,c所求运动员名次的方案数,
  3. falg[]标记观众预测为真的名次,a[][]保存观众的预测*/
  4. int n, m, c, flag[11], a[105][6];
  5. //mc运动员名次,k观众猜测此运动员假名次个数,jiamc[]保存观众猜测此运动员名次为假的名次
  6. struct{
  7. int mc, k, jiamc[105];
  8. }ydy[11];
  9. //per[]为每个方案运动员的名次,sum保存每个方案运动员名次的十进制整数
  10. struct{
  11. int per[11];
  12. long long sum;
  13. } ans[1000], t;
  14. int pj(int n, int mc){//判断n号运动员,mc是否为假
  15. int i;
  16. for(i = 0; i < ydy[n].k; i++){
  17. if(ydy[n].jiamc[i] == mc){
  18. return 0;//mc为假,返回0
  19. }
  20. }
  21. return 1;//mc为真,返回1
  22. }
  23. int shu(int cur){//回溯法把剩余没有名次的运动员根据约束条件补齐
  24. if(cur > n){
  25. int i;
  26. for(i = 1; i <= n; i++){
  27. ans[c].per[i] = ydy[i].mc;
  28. }
  29. c++;
  30. }
  31. else{
  32. int i;
  33. if(ydy[cur].mc == 0){//运动员cur没有名次
  34. for(i = 1; i <= n; i++){//运动员名次
  35. if(flag[i] == 0 && pj(cur, i)){//名次i未被标记且第cur个运动员的名次i不在假名次中
  36. ydy[cur].mc = i;
  37. flag[i] = 1;
  38. shu(cur + 1);
  39. ydy[cur].mc = 0;
  40. flag[i] = 0;
  41. }
  42. }
  43. }
  44. else{//运动员cur有名次
  45. shu(cur + 1);
  46. }
  47. }
  48. }
  49. int search(int cur){
  50. if(cur < m){
  51. int i;
  52. for(i = 0; i < 2; i++){/*i == 0时,假设观众cur第一个预测为真,则其第二个预测为假,
  53. i == 1时,假设观众cur第二个预测为真,则其第一个预测为假 */
  54. if(ydy[a[cur][2 * i + 1]].mc == a[cur][2 * i + 2]){/*观众cur预测同一个运动员的名次
  55. 与之前观众预测相同*/
  56. if(pj(a[cur][3 - 2 * i], a[cur][4 - 2 * i])){//观众cur预测的假名次,还未保存在在该运动员的jiamc[]中
  57. ydy[a[cur][3 - 2 * i]].jiamc[ydy[a[cur][3 - 2 * i]].k] = a[cur][4 - 2 * i];//保存相应运动员名次为假的名次
  58. ydy[a[cur][3 - 2 * i]].k++;//假名次个数增加
  59. search(cur + 1);
  60. ydy[a[cur][3 - 2 * i]].jiamc[ydy[a[cur][3 - 2 * i]].k] = 0;
  61. ydy[a[cur][3 - 2 * i]].k--;
  62. }
  63. else{//观众cur预测的假名次,已经保存在该运动员的jiamc[]中
  64. search(cur + 1);
  65. }
  66. }
  67. else{//观众cur预测不是同一个运动员
  68. //名次未被标记且运动员名次不相同且运动员的jiamc[]等于1,即运动员名次为真,或者第一层
  69. if((flag[a[cur][2 * i + 2]] == 0 && ydy[a[cur][2 * i + 1]].mc == 0 && pj(a[cur][2 * i + 1], a[cur][2 * i + 2])) || cur == 0){
  70. ydy[a[cur][2 * i + 1]].mc = a[cur][2 * i + 2];//保存相应运动员的名次
  71. flag[a[cur][2 * i + 2]] = 1;//标记名次
  72. ydy[a[cur][3 - 2 * i]].jiamc[ydy[a[cur][3 - 2 * i]].k] = a[cur][4 - 2 * i];//保存相应运动员名次为假的名次
  73. ydy[a[cur][3 - 2 * i]].k++;//假名次个数增加
  74. search(cur + 1);
  75. ydy[a[cur][2 * i + 1]].mc = 0;
  76. flag[a[cur][2 * i + 2]] = 0;
  77. ydy[a[cur][3 - 2 * i]].jiamc[ydy[a[cur][3 - 2 * i]].k] = 0;
  78. ydy[a[cur][3 - 2 * i]].k--;
  79. }
  80. }
  81. }
  82. }
  83. else if(cur == m){//cur等于观众人数,进入shu()补齐其余运动员的名次
  84. shu(1);
  85. }
  86. }
  87. int main()
  88. {
  89. int i, j, k;
  90. scanf("%d", &n);
  91. scanf("%d", &m);
  92. for(i = 0; i < m; i++){
  93. scanf("%d %d %d %d", &a[i][1], &a[i][2], &a[i][3], &a[i][4]);
  94. }
  95. search(0);
  96. if(c == 0){//方案数为0
  97. printf("None\n");
  98. return 0;
  99. }
  100. for(i = 0; i < c; i++){//把每一行运动员名次转换成十进制整数
  101. for(j = 1; j <= n; j++){
  102. ans[i].sum = ans[i].sum * 10 + ans[i].per[j];
  103. }
  104. }
  105. for(i = 0; i < c - 1; i++){//通过上面得到的整数从小到大排序,即可得到字典序
  106. k = i;
  107. for(j = k + 1; j < c; j++){
  108. if(ans[j].sum < ans[k].sum){
  109. k = j;
  110. }
  111. }
  112. t = ans[k];
  113. ans[k] = ans[i];
  114. ans[i] = t;
  115. }
  116. for(i = 0; i < c; i++){//输出答案
  117. for(j = 1; j <= n; j++){
  118. if(j == 1){
  119. printf("%d", ans[i].per[j]);
  120. }
  121. else{
  122. printf(" %d", ans[i].per[j]);
  123. }
  124. }
  125. printf("\n");
  126. }
  127. return 0;
  128. }

7-15 单链表基本操作

请编写程序实现单链表插入、删除结点等基本算法。给定一个单链表和一系列插入、删除结点的操作序列,输出实施上述操作后的链表。单链表数据域值为整数。

输入格式:

输入第1行为1个正整数n,表示当前单链表长度;第2行为n个空格间隔的整数,为该链表n个元素的数据域值。第3行为1个正整数m,表示对该链表施加的操作数量;接下来m行,每行表示一个操作,为2个或3个整数,格式为0 k d或1 k。0 k d表示在链表第k个结点后插入一个数据域值为d的结点,若k=0则表示表头插入。1 k表示删除链表中第k个结点,此时k不能为0。注:操作序列中若含有不合法的操作(如在长度为5的链表中删除第8个结点、删除第0个结点等),则忽略该操作。n和m不超过100000。

输出格式:

输出为一行整数,表示实施上述m个操作后的链表,每个整数后一个空格。输入数据保证结果链表不空。

输入样例:

  1. 5
  2. 1 2 3 4 5
  3. 5
  4. 0 2 8
  5. 0 9 6
  6. 0 0 7
  7. 1 0
  8. 1 6

输出样例:

7 1 2 8 3 5 
  1. #include<stdio.h>
  2. typedef struct Node
  3. {
  4. int data;
  5. struct Node*next;
  6. }node;
  7. node* head=NULL;
  8. node* rear; //设置全局变量,便于实现尾插法
  9. void insertend(node* temp) //链表尾插法
  10. {
  11. if(head==NULL)
  12. {
  13. head=temp;
  14. rear=temp;
  15. rear->next=NULL;
  16. }
  17. else
  18. {
  19. rear->next=temp;
  20. rear=temp;
  21. rear->next=NULL;
  22. }
  23. }
  24. void insert(node*temp,int k,int d) //表头插入,第k个结点后插入一个数据域值为d的结点
  25. {
  26. if(k==0)
  27. {
  28. temp->data=d;
  29. temp->next=head;
  30. head=temp;
  31. }
  32. else
  33. {
  34. node* p0=head;
  35. while(k-1>0)
  36. {
  37. p0=p0->next;
  38. k--;
  39. }
  40. temp->next=p0->next;
  41. p0->next=temp;
  42. temp->data=d;
  43. }
  44. }
  45. void delete(int k) //删除链表中第k个结点
  46. {
  47. node* p=head;
  48. int nm=1;
  49. while(p!=NULL&&nm<k-1)
  50. {
  51. p=p->next;
  52. nm++;
  53. }
  54. node*q=p;p=p->next; //p指向第k个结点,q是p的前驱结点
  55. if(p->next!=NULL)
  56. {
  57. q->next=p->next;
  58. free(p);
  59. }
  60. else
  61. {
  62. q->next=NULL;
  63. free(p);
  64. }
  65. }
  66. int main()
  67. {
  68. int n,i;
  69. int num;
  70. node*p;
  71. int m;
  72. scanf("%d",&n);//输入第1行为1个正整数n,表示当前单链表长度
  73. for(i=0;i<n;i++) //创建链表
  74. {
  75. node*n=(node*)malloc(sizeof(struct Node));
  76. insertend(n);
  77. }
  78. p=head; //遍历链表输入data域值
  79. while(p!=NULL)
  80. {
  81. scanf("%d",&num);
  82. p->data=num;
  83. p=p->next;
  84. }
  85. scanf("%d",&m);//第3行为1个正整数m,表示对该链表施加的操作数量
  86. int n1,n2,n3;
  87. for(i=0;i<m;i++)
  88. {
  89. scanf("%d",&n1);
  90. if(n1==0)
  91. {
  92. scanf("%d",&n2);
  93. scanf("%d",&n3);
  94. if(n2>=0&&n2<=n)
  95. {
  96. node*temp=(node*)malloc(sizeof(struct Node));
  97. insert(temp,n2,n3);
  98. n++;
  99. }
  100. }
  101. if(n1==1)
  102. {
  103. scanf("%d",&n2);
  104. if(n2>0&&n2<=n)
  105. {
  106. delete(n2);
  107. n--;
  108. }
  109. }
  110. }
  111. p=head;
  112. while(p!=NULL)
  113. {
  114. printf("%d ",p->data);
  115. p=p->next;
  116. }
  117. return 0;
  118. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/298101
推荐阅读
相关标签
  

闽ICP备14008679号