UESTC 1262 Memory 暴力法

Memory

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit  Status

小x和小h是好盆友,小h从小体弱多病,而且还非常健忘,于是把自己平时吃的 n 瓶药都给小x等人保管。

某一天由于雾都的pm2.5爆表,小h的慢性呼吸道疾病又发作了,但当小x掏出药瓶的时候,却发现了异常情况。

小x现在有n瓶药,每瓶药里面有无限个药片,每片药重量严格等于1克。但是,吹毛求疵的小x发现 n 瓶药中有2瓶药的每一片药片在重量上是不合格

的,不合格的药片比正常药片轻0.1g。

小x现在有一个电子称 ( 能够显示具体重量 ) ,由于时间紧急,小x决定从每瓶药中选择 bi(1bi)   个药片,称量它们的总和,并且只称一次,从而找

出这两瓶不合格药的编号。

现在,请问最小字典序的序列 b(  由 bi 构成 ) 是多少?

Input

一行一个整数 n(2n52)

Output

一行 n 个数字,两两间用空格隔开,注意结尾没有空格。

Sample input and output

Sample Input Sample Output
3
1 2 3

Hint

若  a1,a2..an  比  b1,b2..bn   字典序小,则必存在  j(1jn)    使得  aj  <  bj  且 对于所有 i<j 都有 ai=bi

样例的解释:如果称出来是5.7g,那么就是第1和第2瓶不合格;如果是5.6g,那么就是第1和第3瓶不合格;

如果是5.5g,那么就是第2和第3瓶不合格。

Source

第七届ACM趣味程序设计竞赛第三场(正式赛)E

My Solution

思路是已经有i-1个满足条件的数,再加第i个数进去依然满足,任意两个数的和不会和另外的两数和相等。

前面比赛的时候一直以为是斐波那契数列,结束了学长宣布不是Fib,确实当时笔者自己也感觉到数据很大的时候i-1个数和第i个数会相差很多,
可以相差好多亿(n<=52),所以很可能存在j比Fib第i个数小,但也满足条件。
当时还一直以为是自己漏解,确实应当好好反思一下啊。

那么用暴力法还是比较好的选择了,呵呵,暴力法本来就挺好的。
sum[ i ][ j ]表示第i个数和第j个数的和。反正n<=52,这么整不要紧
先对ans[ i ]的i每一个i进行处理,从j开始递增并在子块 x=i  更新好sum[ x ][前面的数],且在每个里面放forfor对整个矩阵进行扫描,当然,要到x-1行的
时候停下,自己那行可不能扫啊。如果中间出现和相等了直接return,这也是函数相对直接嵌套在里面的好处了,一个return直接跳好几层for。

此外,对于sum[ i ][ j ]可能大部分sum[ i ]的后面部分都没有处理到,却常常会被扫到,但为了使算法写起来理解起来简洁一点,这里不用管它,
记得memset就好了,反正全是0,扫扫更健康。我们要找的是有没有相同和,后面的数的和怎么会和0相等呢☺,(毕竟n<=52,交一发,超时了再改,
虽然不快一般超时不了),所以不用管它。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int sum[56][56],ans[56],n;

inline bool judge(int x,int y)              //这个内联了也基本没有效果,谁叫它太大了啊。
{
    for(int i=1;i<x;i++){
        sum[x][i]=y+ans[i];
        for(int k=1;k<x;k++){              //k当然小于x,不然嘿嘿
            for(int l=1;l<x;l++){          //这里本来是n,也对,写博客的时候临时改为x了,这样相对n快了一点吧,用不到地方少扫几次了
                if(sum[x][i]==sum[k][l]) return false;
                //cout<<sum[k][l]<<" ";
            }
            //printf("\n");
        }
    }
    return true;
}

int main()
{
    scanf("%d",&n);
    memset(sum,0,sizeof(sum));
    if(n==2) printf("1 1");
    else if(n==3) printf("1 2 3");
    else{
        ans[1]=1;ans[2]=2;ans[3]=3;
        sum[1][2]=3;sum[1][3]=4;sum[2][3]=5;

        printf("1 2 3");
        for(int i=4;i<=n;i++){
            for(int j=ans[i-1]+1;;j++){
                if(judge(i,j)){
                    ans[i]=j;
                    printf(" %d",j);
                    break;
                }
            }
        }
    }
    return 0;
}

谢谢

你可能感兴趣的:(ACM,ICPC,OJ,uestc,找规律,暴力法)