zoukankan      html  css  js  c++  java
  • [归并排序][枚举]JZOJ P3967 Counting Friends

    Description

    FJ 的N 头奶牛(2<= N<= 500)都加入了社交网络“哞不可” 。
    每头奶牛有一个或多个与它们自己在哞不可上互相关注的朋友。为了好玩,FJ 制作了一个列表,记下每头奶牛的朋友数目。但是,在书写列表的过程中,农夫John 惆怅了,以至于他错误地写下了一个额外的数字(因此他的列表包含N + 1 个数字,非他预计的N 个数字)。
    请帮助FJ 找出在他的列表中有哪些数字可以是那个错误的额外数字。
     

    Input

    第一行:整数N。
    第2 至N + 2 行:第i + 1 行包含FJ 的某一头奶牛的朋友数量,或者也许是那个错误的额外数字。

    Output

    第一行:一个整数K 给出在FJ 的列表中有多少项目可能是那个额外的数字(或者,K = 0 意味着没有一个数字,移除后可以产生一个可行的朋友配对)。
    第2 至K + 1 行:每行包含可能是额外的数字按照输入顺序产生的序号(1到N +1)——也就是说,一个移除后,剩下的N 个数字符合奶牛们某一个可行
    的朋友关系集合。这K 行的序号须按从小到大排列。
     

    Sample Input

    4
    1
    2
    2
    1
    3

    Sample Output

    3
    1
    4
    5
    样例解释:
    FJ 有4 头奶牛。两头每头只有一个朋友,两头各有两个朋友,还有一头有三个朋友(当然,这些数字其中一个是额外的并且不属于这个列表)。
    移除FJ 列表的第一个数字(数字1)之后会得到一个剩下的数字2,2,1,3 组成的列表,并且符合一个可行的朋友关系配对——例如,如果我们将奶牛从A
    到D 命名,那么配对(A;B); (A;C); (A;D) 以及(B;C) 就足够了,这是因为A有三个朋友,B 和C 都各有两个朋友,还有D 有一个朋友。同理,从FJ 的列表里移除另外一个“1”也是可行的,还有移除“3”也可以。从FJ 的列表里移除任意一个“2”都不可——我们可以看到剩下数字的和是奇数,明显我们无法凑出一个对应的配对。
     

    Data Constraint

    对于9% 的数据,N <=10。
    对于27% 的数据,N <=100。

    题解

    • 这题用的是比较暴力的方法
    • 首先,我们知道该数字可以为额外的话,也就是其他的n个都可以匹配成需要那样、
    • 那么就暴力枚举n+1个数,判断哪个可以为额外的数字
    • 怎么匹配呢
    • 其实有一种很简单的想法
    • 就是从大到小排序,向后匹配(也就是往后的2~a[1]+1个都减1)
    • 如果是可以匹配的数的话,这个方法一定是可以匹配的
    • 那么我们考虑一下时间复杂度,每次一个数要O(n^2(n+n*log2n))
    • 只能过6个点
    • 那么快排的时间可以不可以更优呢?
    • 考虑一下,减完之后的序列为0+有序的序列(2~a[1]+1)+有序的序列(a[1]+2~n)
    • 有那种方法是可以直接在O(n)的时间下合并两个有序的序列呢?
    • 显然归并排序
    • 最后判断一波,输出,AC,perfect

    代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 using namespace std;
     5 bool cmp(int x,int y){ return x>y; }
     6 int n,a[510],x[510],y[510],tot,total,ans[510];
     7 int main()
     8 {
     9     scanf("%d",&n);
    10     for (int i=1;i<=n+1;i++) scanf("%d",&a[i]);
    11     for (int i=1;i<=n+1;i++)
    12     {
    13         tot=0;
    14         for (int j=1;j<=n+1;j++) 
    15             if (i!=j)
    16                 x[++tot]=a[j];
    17         sort(x+1,x+n+1,cmp);
    18         while (x[1]>0)
    19         {
    20             for (int j=2;j<=x[1]+1;j++) x[j]--;
    21             int l1=2,r1=x[1]+1,l2=x[1]+2,r2=n; 
    22             tot=0; x[1]=0;
    23             while (l1<=r1&&l2<=r2)
    24             {
    25                 if (x[l1]<=x[l2]) y[++tot]=x[l2],l2++;
    26                 else y[++tot]=x[l1],l1++;
    27             }
    28             while (l1<=r1) y[++tot]=x[l1],l1++;
    29             while (l2<=r2) y[++tot]=x[l2],l2++;
    30             for (int j=1;j<=n;j++) x[j]=y[j];
    31         }
    32         sort(x+1,x+n+1,cmp);
    33         if (x[n]==0) ans[++total]=i;
    34     }
    35     printf("%d
    ",total);
    36     for (int i=1;i<=total;i++) printf("%d
    ",ans[i]);
    37     return 0;
    38 }
  • 相关阅读:
    c语言知识
    数字地与模拟地
    C语言实现顺序表(增删)
    传统数据库、Nosql数据库与云数据库区别?
    大数据处理架构如何
    warning: implicit declaration of function 'func1' [-Wimplicit-function-declaration]
    window10创建virtualenv虚拟环境
    二叉树的实现以及三种遍历方法--代码
    损失函数--KL散度与交叉熵
    市场回测与对冲套利
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8562140.html
Copyright © 2011-2022 走看看