2020-10-28

解题思路1、紧紧抓住条件,课程编号只有1-n,那么实际上每个课程最后只会放入数组相应的下标,比如有数据:

3   4   5    2    1

那么最后课程编号3只能被放入第三个位置,课程编号1只能放入第一个位置。

因此首先有个绝对不可能成功的判定条件:

那就是奇数课程编号只能放在奇数的下标位置、偶数的课程编号只能放在偶数的下标位置!!!!因为每次换是隔一个的。

if(a[i]%2 != (i+1)%2){
    printf("-1\n"); 
    tag = 1;
    break;
}

然后就是怎么换次数最少?

实际上我们根本就不用理会中间的过程,值需要知道课程编号为5的一定要放到第五个位置去,那当然我们直奔目标是最快的!!!!

所以直接计算课程编号和当前位置爹差值/2就是最少的操作次数,举例:

课程编号5,应该放在第五个位置,但是目前挡灾第3个位置,因此需要挪动的最少次数是(5-3)/2 = 1

其余同理,然后我们每次值需要计算课程编号应该放的位置比当前的位置大的即可,其余的情况会在我们排列的时候自动排列好!!!

//只需要标号大的懂,小的自己就排列好了
if(a[i]-i>1)
       ans += (a[i]-(i+1))/2;

下面是思路的整体代码:

#include <stdio.h>
int main()
{
 int a[1086];
 int t, n, i, j, k=1, tag=0, ans;
 scanf("%d", &t);
 while (k<=t)
 {
  k++;
  scanf("%d",&n);
  // 这不是坑我胖虎吗,数组一般都是从0开始读取,哪有从1的
  for(i=0;i<n;i++)
   scanf("%d",&a[i]);
  /*
   解题关键是发现规律,编号为i的课程一定要放到数组下标i的位置,然后因为每次交换都是
   隔一个进行交换,那么因为课程编号的奇、偶性一定不会变化,比如有:
   3 4 1 5 2
   2在第5个位置,那么不管怎么交换都只能在奇数的位置上(第一个、第三个、第五个)
   因此如何用最少的次数放回正确的位置呢??这是这个题目的难点
  */
  ans = 0;
  for(i = 0;i < n;i++){
   if(a[i]%2 != (i+1)%2){
    printf("-1\n"); 
    tag = 1;
    break;
       }
       //只需要标号大的懂,小的自己就排列好了
       if(a[i]-i>1)
       ans += (a[i]-(i+1))/2;
   //printf("ans:%d\n",ans);
  }
  if(tag!=1) printf("%d\n",ans);
  tag = 0;
 }
 return 0;
}

这个算法的时间复杂度是O(N)

解题思路二、可以利用dfs(deep first search,深度优先遍历,类似之前数组变换拿到题目,这个解法我先不写,你先掌握上面哪个)

 

这是一个 SQL 语句,用于向借阅表中插入数据。该表包含以下字段:借阅编号、读者编号、书籍编号、借阅日期、归还日期、借阅状态。每条数据表示一次借阅记录。其中借阅编号、读者编号、书籍编号、借阅日期和借阅状态是必填项,归还日期为可选项,如果借阅状态为“已还”则必须填写归还日期。 具体插入的数据如下: - 借阅编号:100001,读者编号:123413,书籍编号:0001,借阅日期:2020-11-05,归还日期:NULL,借阅状态:借阅 - 借阅编号:100002,读者编号:223411,书籍编号:0002,借阅日期:2020-9-28,归还日期:2020-10-13,借阅状态:已还 - 借阅编号:100003,读者编号:321123,书籍编号:1001,借阅日期:2020-7-01,归还日期:NULL,借阅状态:过期 - 借阅编号:100004,读者编号:321124,书籍编号:2001,借阅日期:2020-10-09,归还日期:2020-10-14,借阅状态:已还 - 借阅编号:100005,读者编号:321124,书籍编号:0001,借阅日期:2020-10-15,归还日期:NULL,借阅状态:借阅 - 借阅编号:100006,读者编号:223411,书籍编号:2001,借阅日期:2020-10-16,归还日期:NULL,借阅状态:借阅 - 借阅编号:100007,读者编号:411111,书籍编号:1002,借阅日期:2020-9-01,归还日期:2020-9-24,借阅状态:已还 - 借阅编号:100008,读者编号:411111,书籍编号:0001,借阅日期:2020-9-25,归还日期:NULL,借阅状态:借阅 - 借阅编号:100009,读者编号:411111,书籍编号:1001,借阅日期:2020-10-08,归还日期:NULL,借阅状态:借阅
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值