您的位置:首页 > 产品设计 > UI/UE

UESTC 1262 Memory 暴力法

2015-12-12 23:46 531 查看


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(1≤bi)
个药片,称量它们的总和,并且只称一次,从而找
出这两瓶不合格药的编号。
现在,请问最小字典序的序列b( 由bi构成)是多少?


Input

一行一个整数n(2≤n≤52)


Output

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


Sample input and output

Sample InputSample Output
3

1 2 3


Hint

若 a1,a2..an 比 b1,b2..bn
字典序小,则必存在 j(1≤j≤n)
使得 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;
}


谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: