UVA10202Pairsumonious Numbers

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21246

题意:给定一个数字n,代表最多有n个方程解,再给出(n-1*n/2个值a,对应不知道的任意两个数的和。把这些数的方案求出来,输出一种。若没有,输出Impossible

思路:线性方程组,看了题解才会做,比赛的时候都没什么人做说明大家其实挺LOW的。给a排序,其中a[0]a[1]分别为x[0]+x[1]x[0]+x[2]的解。这时候向后遍历a[k] = x[0]+x[2],得出x[2]。根据每次遍历最小值均为a[m] = x[m0]+x[0],把所有数标记上,若存在未标记的数,则此种情况不和条件,k向后,再次重复操作。

错误点第一是没有思路,对线性方程不熟悉,用了矩阵求秩的方法去求,结果繁琐不说,还带有很大的随机性。第二是不明白x[0]+x[m0]m0可以为任意值)<x[1]+x[2]的可存在性,注意m0为任意值。第三vis数组开小(MD

源码:#include <cstdio>

#include <cmath>

#include <cstring>

#include <algorithm>

using namespace std;

int const MAXN = 10+5;

int a[MAXN*MAXN/2],b[MAXN],n,vis[MAXN*MAXN/2],m;

//int st[MAXN] = {0,0,1,3,6,10,15,21,27};

int gmin(int a,int b){return a<b?a:b;}

int find_min()

{

    int i;

    for(i=0; i<m; i++)

        if(vis[i]==0)

            break;

    return i;

}

void del(int tt)

{

    for(int i=0; i<m; i++){

        if(a[i]==tt && vis[i]==0){

            vis[i]=1;

            return;

        }

    }

}

void check()

{

    int i,j;

    printf("a = ");

    for(i=0; i<m; i++)

        printf("%d ",a[i]);

    printf("\nvis = ");

    for(i=0; i<m; i++)

        printf("%d ",vis[i]);

    printf("\nb = ");

    for(i=0;i<n; i++)

        printf("%d ",b[i]);

    printf("\n");

}

int main()

{

    while(scanf("%d",&n)!=EOF){

        int flag = 0;

        memset(vis,0,sizeof(vis));

        int i,j,k;

        m = n*(n-1)/2;

        for(i=0; i<m; i++)

            scanf("%d",&a[i]);

        sort(a,a+m);

        for(k=2; k<m; k++){

//            printf("\nk = %d\n",k);

            flag = 0;

            if((a[0]+a[1]-a[k])%2!=0){

                flag = 1;

                continue;

            }

            b[0] = (a[0]+a[1]-a[k])/2;

            b[2] = a[1] - b[0];

            b[1] = a[0] - b[0];

            if(b[1]+b[2]!=a[k]){

                flag = 1;

                continue;

            }

            vis[0] = vis[1] = vis[k] = 1;

            for(i=3; i<n; i++){

                b[i] = a[find_min()] - b[0];

                for(j=0; j<i; j++)

                    del(b[j]+b[i]);

            }

            for(i=0; i<m ;i++){

                if(vis[i]==0){

                    flag = 1;

                    break;

                }

            }

//            check();

            memset(vis,0,sizeof(vis));

            if(flag==0)

                break;

        }

        if(flag)

            printf("Impossible\n");

        else{

            sort(b,b+n);

            int f = 1;

            for(i=0; i<n; i++){

                if(f)   f=0;

                else printf(" ");

                printf("%d",b[i]);

            }

            printf("\n");

        }

    }

    return 0;

}

 

你可能感兴趣的:(个人赛)