• SCNU 2015ACM新生赛初赛【1007. ZLM的扑克牌】解题报告


     
          题目链接详见SCNU 2015新生网络赛 1007. ZLM的扑克牌
     
          其实我在想这题的时候,还想过要不要设置求最小的排列,并且对于回文数字的话,可以把扑克牌折起来(从而这个数字会变小);甚至要不要设置扑克牌旋转、翻转之后,读出的数字要改变。但这样的话好像我也不会做辣!= =|||于是这道题目最后就变成了一个简单贪心题。题目大意大概就是这样的:给出一个包含$n$个数字的多重集,要求使用集合中的元素拼凑出一个最大的数字,问最大所能拼凑出的数字是多少?
     
          贪心算法需要对贪心策略进行证明。比如大部分同学可能会想到的是,做一个简单的排序,把数字大的排在前面,数字小的排在后面,然后按顺序输出就好啦!但很可惜这是错的!因为对于$12345$,它比$67$要大,但$67$应该排在它的前面,因为$1234567$是小于$6712345$的。
     
          我们考虑两个数字串$A$和$B$,组合得到一个新的数字串$AB$或$BA$,定义关系$succ$,当且仅当$AB > BA$严格成立时,$A succ B$成立。对于集合中另一个数字串$C$且$A succ B$,如果$C succ A$,则一定满足$C succ B$;如果$B succ C$,则一定满足$A succ C$;否则应当再进行一次比较以确定$A$、$B$、$C$三者的序关系。对于全集$S_{N}$,至多进行有限次即$O(N^{2})$的比较可以使整个集合满足全序关系,于是基于这种比较的排序方法可行。
     
          接下来考虑下代码,因为输入输出量比较大,而时限只有1s,所以C++的输入输出方法被卡得死死的,只要使用了就一定会TLE。另外STL的string类也会导致TLE,这个我原先倒是没想过要卡的,但至少给大家一个警醒,不要滥用STL,STL大概为了做到泛型编程和通用性,通常会损失一些性能,因此在某些时候远不及于自己写的代码。
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 namespace cmp {
     6     char tx[15], ty[15];
     7     int compare(const void*a, const void*b) {
     8         strcat(strcpy(tx, (char*)a), (char*)b);
     9         strcat(strcpy(ty, (char*)b), (char*)a);
    10         return strcmp(ty, tx);
    11     }
    12 }
    13 
    14 char x[10001][7];
    15 int main() {
    16     int cse, T, N, i;
    17     scanf("%d", &T);
    18     for(cse=1; cse<=T; cse++) {
    19         printf("Case #%d:
    ", cse);
    20         scanf("%d", &N);
    21         for(i=0; i<N; i++)
    22             scanf("%s", x[i]);
    23         qsort(x, N, 7, cmp::compare);
    24         for(i=0; i<N; i++)
    25             printf(x[i]);
    26         puts("");
    27     }
    28     return 0;
    29 }
     
          上面的代码用了C++的命名空间,你也可以选择用函数内静态变量,或直接暴露成全局变量。其中利弊请自行体会= =||
          另外注意一下我在qsort的compare中写的是strcmp(ba,ab),其中原因请参看strcmp函数返回值说明以及qsort函数参数说明,并注意一下$a$和$b$之间的关系。
     
          附:数据生成程序如下:
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <math.h>
     4 #include <time.h>
     5 
     6 int main() {
     7     freopen("in.txt", "w+", stdout);
     8     int T = 100;
     9     printf("%d
    ", T);
    10     srand(time(NULL));
    11     for(int a=1; a<=4; a++)
    12         for(int b=0; b<a*10; b++) {
    13             int N = rand()%((int)pow(10, a)-2)+2;
    14             printf("%d
    ", N);
    15             for(int i=0; i<N; i++) {
    16                 int X = rand()%((int)pow(10, 6-a)-1)+1+(int)pow(rand()%10, 7-a);
    17                 printf("%d ", X);
    18             }
    19             puts("");
    20     }
    21     return 0;
    22 }
    Click To View Code
     
  • 相关阅读:
    Linux OTG当串口、网口、U盘
    Linux 双网卡双网段通信
    Buildroot Savedefconfig
    OTG作为大容量设备
    EntityFramework Core问题处理集锦(一)
    EntityFramework Core数据查询
    ASP.NET Core MVC请求超时设置解决方案
    EntityFramework Core迁移时出现数据库已存在对象问题解决方案
    EntityFramework Core映射关系详解
    探讨SQL Server并发处理存在就更新七种解决方案
  • 原文地址:https://www.cnblogs.com/BlackStorm/p/4988586.html
Copyright © 2020-2023  润新知