zoukankan      html  css  js  c++  java
  • P1433 吃奶酪 回溯法 优化

      

    题目描述

    房间里放着n块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处。

    输入输出格式

    输入格式:

    第一行一个数n (n<=15)

    接下来每行2个实数,表示第i块奶酪的坐标。

    两点之间的距离公式=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))

    输出格式:

    一个数,表示要跑的最少距离,保留2位小数。

    输入输出样例

    输入样例#1: 复制
    4
    1 1
    1 -1
    -1 1
    -1 -1
    输出样例#1: 复制
    7.41

    一开始回溯法显然超时
    然后加了一个剪枝勉强能过
    不过花了800+ms
    #include<bits/stdc++.h>
    using namespace std;
    //input
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m);
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define inf 0x3f3f3f3f
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define N
    int n;
    struct node
    {
        double x,y;
    }s[20];
    int vis[20];
    double dd(node a,node b )
    {
      return sqrt( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) );
    }
    double mind=inf;
    
    void dfs(int cur,int cnt,double d)
    {
       if(cnt==n)
       {
           mind=min(mind,d);
           return ;
       }
       if(d>=mind)return ;//关键剪枝
        rep(i,1,n)
        {
            if(vis[i])continue;
            vis[i]=1;
            dfs(i,cnt+1,d+dd( s[cur],s[i] ));
            vis[i]=0;
        }
        return ;
    }
    int main()
    {
        RI(n);
        rep(i,1,n)
        cin>>s[i].x>>s[i].y;
        
        rep(i,1,n)
        vis[i]=1,dfs(i,1,sqrt(s[i].x*s[i].x+s[i].y*s[i].y) ),vis[i]=0;
        
        printf("%.2lf",mind);
        return 0;
    }
    View Code

    按照曼哈顿距离排序的话剪了30ms。。。


    n<=15的回溯法就接近爆时间

    加上一个剪枝可以进行一定程度的优化
    预处理两点距离即可
    580ms
    #include<bits/stdc++.h>
    using namespace std;
    //input
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m);
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define inf 0x3f3f3f3f
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define N
    int n;
    struct node
    {
        double x,y;
    }s[20];
    int vis[20];
    double dd(node a,node b )
    {
      return sqrt( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) );
    }
    double mind=inf;
    
    double dis[20][20];
    
    void dfs(int cur,int cnt,double d)
    {
       if(cnt==n)
       {
           mind=min(mind,d);
           return ;
       }
       if(d>=mind)return ;//关键剪枝
        rep(i,1,n)
        {
            if(vis[i])continue;
            vis[i]=1;
            dfs(i,cnt+1,d+dis[cur][i]);
            vis[i]=0;
        }
        return ;
    }
    int main()
    {
        RI(n);
        rep(i,1,n)
        cin>>s[i].x>>s[i].y;
    
        rep(i,1,n)
        rep(j,1,n)
        dis[i][j]=dd(s[i],s[j]);
    
        rep(i,1,n)
        vis[i]=1,dfs(i,1,sqrt(s[i].x*s[i].x+s[i].y*s[i].y) ),vis[i]=0;
    
        printf("%.2lf",mind);
        return 0;
    }
    View Code
  • 相关阅读:
    Python Challenge 第 5 关攻略:peak
    Python Challenge 第 4 关攻略:linkedlist
    Python Challenge 第 2 关攻略:ocr
    网站工具
    python使用twisted搭建的一个socket服务
    集合的使用
    开启vmotion,实现虚拟机可以在线迁移的选项
    windows-x64下安装python3.6
    第二天课程的心得体会以及小结
    购物车作业的优化
  • 原文地址:https://www.cnblogs.com/bxd123/p/10662026.html
Copyright © 2011-2022 走看看