zoukankan      html  css  js  c++  java
  • C. Looking for Order

    题目链接:http://codeforces.com/problemset/problem/8/C

    C. Looking for Order
    time limit per test
    4 seconds
    memory limit per test
    512 megabytes
    input
    standard input
    output
    standard output

    Girl Lena likes it when everything is in order, and looks for order everywhere. Once she was getting ready for the University and noticed that the room was in a mess — all the objects from her handbag were thrown about the room. Of course, she wanted to put them back into her handbag. The problem is that the girl cannot carry more than two objects at a time, and cannot move the handbag. Also, if he has taken an object, she cannot put it anywhere except her handbag — her inherent sense of order does not let her do so.

    You are given the coordinates of the handbag and the coordinates of the objects in some Сartesian coordinate system. It is known that the girl covers the distance between any two objects in the time equal to the squared length of the segment between the points of the objects. It is also known that initially the coordinates of the girl and the handbag are the same. You are asked to find such an order of actions, that the girl can put all the objects back into her handbag in a minimum time period.

    Input

    The first line of the input file contains the handbag's coordinates xs, ys. The second line contains number n (1 ≤ n ≤ 24) — the amount of objects the girl has. The following n lines contain the objects' coordinates. All the coordinates do not exceed 100 in absolute value. All the given positions are different. All the numbers are integer.

    Output

    In the first line output the only number — the minimum time the girl needs to put the objects into her handbag.

    In the second line output the possible optimum way for Lena. Each object in the input is described by its index number (from 1 to n), the handbag's point is described by number 0. The path should start and end in the handbag's point. If there are several optimal paths, print any of them.

    Examples
    input
    Copy
    0 0
    2
    1 1
    -1 1
    output
    Copy
    8
    0 1 2 0
    input
    Copy
    1 1
    3
    4 3
    3 4
    0 0
    output
    Copy
    32
    0 1 2 0 3 0

    题意:

    一个平面上放着许多东西,每个东西都有一个坐标,最开始一个人在一个起始坐标,她出发去拿东西,一次要么拿一件东西,要么拿两件东西,拿了之后必须返回起始坐标。

    每次花费的时间是两个坐标距离的平方,问拿完所有的东西需要的最少的时间。

    思路:状压dp,考虑每次取一个或者两个的情况,但是代码中的break不是很懂

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<stack>
    #include<map>
    #include<queue>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ull;
    #define sc1(a) scanf("%lld",&a)
    #define pf1(a) printf("%lld
    ",a)
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    const LL INF=1e18;
    const ull base=2333;
    const int maxn=1e1+50;
    const int maxm=1e2+50;
    const int maxv=1e6+5;
    const int mod=1e9+7;
    const int ba=3e5;
    struct Node
    {
        LL x,y;
    }a[maxn];
    LL N;
    LL dis[maxn][maxn];
    LL dp[1<<24];//dp[s] 当前得到的集合为s 因为起点只能是1  得到一个或者两个 所以一维就够了
    LL now[1<<24],last[1<<24];
    vector<LL>ans;
    void Init()
    {
        for(int i=0;i<(1<<N);i++)
        {
            dp[i]=INF;
            now[i]=last[i]=-1;
        }
    }
    LL Cal_Node(Node xx,Node yy)
    {
        return (xx.x-yy.x)*(xx.x-yy.x)+(xx.y-yy.y)*(xx.y-yy.y);
    }
    void Cal_dis()
    {
        for(int i=0;i<=N;i++)
        {
            for(int j=0;j<=N;j++)
            {
                dis[i][j]=Cal_Node(a[i],a[j]);
            }
        }
    }
    void Solve()
    {
        dp[0]=0;
        for(int s=0;s<(1<<N);s++)
        {
            for(int i=1;i<=N;i++)
            {
                if((s&(1<<(i-1)))==0)// s不包含i 选i
                {
                    LL v=dis[0][i]*2;//并且回到手提包的位置 选一次
                    //还得记录路径
                    if(dp[s]+v<dp[s|(1<<(i-1))])
                    {
                        dp[s|(1<<(i-1))]=dp[s]+v;
                        now[s|(1<<(i-1))]=i;//
                        last[s|(1<<(i-1))]=s;//从s过来
                    }
                    //选两次 再选一个j
                    for(int j=i+1;j<=N;j++)
                    {
                        if((s&(1<<(j-1)))==0) //选i和j
                        {
                            v=dis[0][i]+dis[i][j]+dis[j][0];
                            if(dp[s]+v<dp[s|(1<<(i-1))|(1<<(j-1))])
                            {
                                dp[s|(1<<(i-1))|(1<<(j-1))]=dp[s]+v;
                                last[s|(1<<(i-1))|(1<<(j-1))]=s;
                                now[s|(1<<(i-1))|(1<<(j-1))]=i*100+j;//存两位
                            }
    //                        dp[s|(1<<(i-1))|(1<<(j-1))]=min(dp[s|(1<<(i-1))|(1<<(j-1))],dp[s]+v);
                        }
                    }
                    break;
                }
            }
        }
    //    for(int i=0;i<(1<<N);i++) cout<<dp[i]<<" "<<endl;
    }
    void Print(LL x)
    {
        if(x==0) return ;
        if(last[x]!=-1)
        {
            Print(last[x]);//一直递归到最开始
        }
        if(now[x]>100) ans.push_back(now[x]/100);
        ans.push_back(now[x]%100);
        ans.push_back(0);
    }
    int main()
    {
        sc1(a[0].x);sc1(a[0].y);//手提包的坐标
        sc1(N);
        Init();
        for(int i=1;i<=N;i++)
        {
            sc1(a[i].x);sc1(a[i].y);
        }
        Cal_dis();
        Solve();
        pf1(dp[(1<<N)-1]);
        Print((1<<N)-1);
        printf("0");
        for(int i=0;i<ans.size();i++)
        {
            printf(" %d",ans[i]);
        }
        printf("
    ");
        return 0;
    }
    /**
    
    */
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    Android UI开发第二十四篇——Action Bar
    Android ActionBar使用方法
    Eclipse快捷键 10个最有用的快捷键
    android 布局文件中控件ID、name标签属性的命名包含“@”、“.”、“+”等等符号的含义
    tools:context=".MainActivity的作用
    Android 抽屉效果的导航菜单实现
    Dump 文件生成与分析
    WinDbg-如何抓取dump文件
    HTML最全标签
    css文字飞入效果
  • 原文地址:https://www.cnblogs.com/caijiaming/p/12317545.html
Copyright © 2011-2022 走看看