[LuoguP1286]两数之和

[LuoguP1286]两数之和

题目描述

链接

题解

假设当前和为:a1,a2,a3……,an

假设a1<a2<a3……<an

那么a1+a2,a1+a3就被确定了

如果我们知道a1和a1+另一个数的和我们就可以算出另一个数

考虑枚举a1,就可以解出a2,a3

那如何解出a4

就需要知道a1+a4,而我们不知道a1+a4和a2+a3的大小关系

但我们已经知道了a2+a3的确切值,所以可以找到a4的值

多组数据好坑。。。

具体看代码

#include<bits/stdc++.h>

using namespace std;

inline int read()
{
    int f=1,x=0;
    char ch;
    do
    {
        ch=getchar();
        if(ch=='-') f=-1;
    }while(ch<'0'||ch>'9');
    do
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return f*x;
} 

int n;
int num;
int a[100 + 10];
int ans[100 + 10],top;
map<int,int>cnt;

inline void print()
{
    for(int i=1;i<=n;i++)
    {
        printf("%d ",ans[i]);
    }
    cout<<endl;
}

inline bool dfs(int x)
{
    cnt.clear();
    ans[1]=x;ans[2]=a[1]-x;ans[3]=a[2]-x;
    top=3;
    cnt[ans[2]+ans[3]]++;
    for(int i=3;i<=num;i++)
    {
        if(cnt[a[i]])
        {
            cnt[a[i]]--;
            continue;
        }
        ans[++top]=a[i]-x;
        if(top>n) return false;
        for(int j=2;j<=top-1;j++)
        {
            if(ans[top]+ans[j]>a[num]) return false;
            cnt[ans[top]+ans[j]]++;
        }
    }
    return true;
}

int main()
{
    while(scanf("%d",&n)==1) 
    {
        num=n*(n-1)/2;
        for(int i=1;i<=num;i++) a[i]=read();
        sort(a+1,a+num+1);
        bool flag=0;
        for(int i=1;i<=a[1]/2;i++)
        {
            if(dfs(i))
            {
                flag=1;
                print();
            }
        }
        if(!flag)
        cout<<"Impossible"<<endl;
    } 
    return 0;
}
原文地址:https://www.cnblogs.com/wlzs1432/p/11227903.html