Restore Points Gym

来源:互联网 发布:网络发短信平台 编辑:程序博客网 时间:2024/05/18 20:06

http://codeforces.com/gym/101498/problem/M

题意 有n个点 排列在一条直线上 题目给出任意两个点之间距离。
要你给出一种方案(存在多解),使之满足题目条件。 按坐标升序排列。
题目保证总有一个点在原点,点可以重叠。
解题思路:
嗯 n<=18 首先 我们把所有点的距离排序 最远的那一个设为dis。
则0和dis肯定在原序列中,这样最多还剩16个点。
看了gym里的讨论,得到思路。。 dfs暴搜。
首先,因为我们只要输出一种情况。 那么 我们可以这么写
找到两条线段a,b,他们满足a+b=dis. 那么这两个线段肯定可以被认为是一个合法点和两端点的距离。 然后我们分别讨论a,b在这个点的左边哪个在这个点的右边即可。 一共16层递归 每层dfs有2个分支(为什么只有两个分支呢,既然题目保证有解,那么每次只要找到一个合法的a,b就行了,这也也能避免重复。。。) 复杂度是2^16 完全可以接受。
优雅的暴力QAQ

#include <algorithm>#include <cstdio>#include <cstring>#include<iostream>#include<string>#include <cstdlib>#include<queue>#include<set>using namespace std;const int MAX=2e5+5;typedef long long LL;int flag=0;int vec[433];int ans[433];int vis[1000005];int n;int dis;int top;bool check(int ed,int x){    int flag=1;    for(int i=1;i<ed;i++)    {        vis[abs(ans[i]-x)]--;        if(vis[abs(ans[i]-x)]<0)            flag=0;    }    for(int i=1;i<ed;i++)    {        vis[abs(ans[i]-x)]++;    }    return flag;}void dfs(int h){    if(h>n)    {        flag=1;        return ;    }    for(int i=1;i<top;i++)    {        if(vis[vec[i]]&&vis[dis-vec[i]])        {            if(check(h,vec[i]))            {                ans[h]=vec[i];                for(int j=1;j<h;j++)                    vis[abs(ans[j]-vec[i])]--;                dfs(h+1);                if(flag) return ;                for(int j=1;j<h;j++)                    vis[abs(ans[j]-vec[i])]++;            }            if(check(h,dis-vec[i]))            {                ans[h]=dis-vec[i];                int cnt=dis-vec[i];                for(int j=1;j<h;j++)                vis[abs(ans[j]-cnt)]--;               dfs(h+1);                if(flag) return ;               for(int j=1;j<h;j++)                   vis[abs(ans[j]-cnt)]++;            }            break;// 很关键  剪枝  不加超时        }    }}bool cmp(int &a,int &b){    return a>b;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        flag=0;        memset(vis,0,sizeof vis);        memset(vec,0,sizeof vec);        memset(ans,0,sizeof ans);        scanf("%d",&n);        top=n*(n-1)/2;        for(int i=0;i<top;i++)        {            scanf("%d",&vec[i]);            vis[vec[i]]++;        }        sort(vec,vec+top,cmp);        dis=vec[0];        ans[1]=dis;        ans[2]=0;        vis[dis]--;        dfs(3);        {            sort(ans+1,ans+1+n);            for(int i=1;i<=n;i++)            {                if(i-1)                    printf(" %d",ans[i]);                else                    printf("%d",ans[i]);            }        }        puts("");    }}
原创粉丝点击