zoukankan      html  css  js  c++  java
  • 牛客小白月赛22

    链接:https://ac.nowcoder.com/acm/contest/4462/D
    来源:牛客网


    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld

    题目描述

    我们把房间按照笛卡尔坐标系进行建模之后,每个点就有了一个坐标。
    假设现在房子里有些纸片需要被收集,收集完纸片你还要回归到原来的位置,你需要制定一个策略来使得自己行走的距离最短。
    你只能沿着 x 轴或 y 轴方向移动,从位置 (i,j) 移动到相邻位置 (i+1,j),(i-1,j),(i,j+1) 或 (i,j-1) 距离增加 1。

    输入描述:

    在第一行中给出一个T,1T10, 代表测试数据的组数。
    对于每组输入,在第一行中给出房间大小,第二行给出你的初始位置。
    接下来给出一个正整数 n,1≤n≤10 代表纸片的个数。
    接下来 n 行,每行一个坐标代表纸片的位置。
    保证房间小于 20×20 ,纸片一定位于房间内。

    输出描述:

    对于每组输入,在一行中输出答案。
    格式参见样例。

    输入

    1
    10 10
    1 1
    4
    2 3
    5 5
    9 4
    6 5

    输出

    The shortest path has length 24

    一、全排列暴力枚举

    因为最多只有10片纸片,所以大可枚举所有的收集顺序,然后在其中取一个最小值。

    我们可以用求1~k的全排列,计算所有可能的走法,由于纸片数不超过10,所以走法最多只有10!种。

    直接全排列计算即可,用DFS或next_permutation均可。

    DFS求全排列:

     1 #include <bits/stdc++.h>
     2 typedef long long LL;
     3 const int INF=0x3f3f3f3f;
     4 const double eps =1e-8;
     5 const int mod=1e9+7;
     6 const int maxn=1e5+10;
     7 using namespace std;
     8 
     9 int n,m,k;
    10 int stx,sty;
    11 pair<int,int> pos[15];
    12 int vis[15];
    13 int ans;
    14 
    15 void DFS(int x,int y,int num,int step)
    16 {
    17     if(num==0)
    18     {
    19         step+=abs(x-stx)+abs(y-sty);
    20         if(step < ans) ans=step;
    21         return ;
    22     }
    23     for(int i=1;i<=k;i++)
    24     {
    25         if(vis[i]==0)
    26         {
    27             vis[i]=1;
    28             int xx=pos[i].first, yy=pos[i].second;
    29             DFS(xx,yy,num-1,step+abs(xx-x)+abs(yy-y));
    30             vis[i]=0;
    31         }
    32     }
    33 }
    34 
    35 
    36 int main()
    37 {
    38     #ifdef DEBUG
    39     freopen("sample.txt","r",stdin);
    40     #endif
    41     
    42     int T;
    43     scanf("%d",&T);
    44     while(T--)
    45     {
    46         memset(vis,0,sizeof(vis));
    47         ans=INF;
    48         scanf("%d %d %d %d %d",&n,&m,&stx,&sty,&k);
    49         for(int i=1;i<=k;i++)
    50         {
    51             int x,y;
    52             scanf("%d %d",&x,&y);
    53             pos[i]={x,y};
    54         }
    55         DFS(stx,sty,k,0);
    56         printf("The shortest path has length %d
    ",ans);
    57     }
    58     
    59     return 0;
    60 }

    next_permutation求全排列

     1 #include <bits/stdc++.h>
     2 typedef long long LL;
     3 const int INF=0x3f3f3f3f;
     4 const double eps =1e-8;
     5 const int mod=1e9+7;
     6 const int maxn=1e5+10;
     7 using namespace std;
     8 
     9 pair<int,int> pos[15];
    10 int rk[15];
    11 
    12 int main()
    13 {
    14     #ifdef DEBUG
    15     freopen("sample.txt","r",stdin);
    16     #endif
    17     
    18     int T;
    19     scanf("%d",&T);
    20     while(T--)
    21     {
    22         int n,m,k,stx,sty;
    23         int ans=INF;
    24         scanf("%d %d %d %d %d",&n,&m,&stx,&sty,&k);
    25         for(int i=1;i<=k;i++)
    26         {
    27             int x,y;
    28             scanf("%d %d",&x,&y);
    29             pos[i]={x,y}; rk[i]=i;
    30         }
    31         do
    32         {
    33             int sum=0, prex=stx, prey=sty;
    34             for(int i=1;i<=k;i++)
    35             {
    36                 int x=pos[rk[i]].first, y=pos[rk[i]].second;
    37                 sum+=abs(x-prex)+abs(y-prey);
    38                 prex=x; prey=y;
    39             }
    40             ans=min(ans,sum+abs(prex-stx)+abs(prey-sty));
    41         }while(next_permutation(rk+1,rk+1+k));
    42         printf("The shortest path has length %d
    ",ans);
    43     }
    44     
    45     return 0;
    46 }

    二、状压dp

    把每个纸片都不重不漏地恰好经过一次,很容易想到旅行商问题,即TSP问题(每个城市只能拜访一次,而且最后要回到原来出发的城市。),可以用状压dp。

    借助二进制数来进行DP。

     1 #include <bits/stdc++.h>
     2 typedef long long LL;
     3 const int INF=0x3f3f3f3f;
     4 const double eps =1e-8;
     5 const int mod=1e8;
     6 const int maxn=1e5+10;
     7 using namespace std;
     8 
     9 pair<int,int> pos[15];
    10 int dp[1<<11][11];//dp[i][j]目前走过的状态是二进制i,且最后一个走过的点是j 
    11 
    12 int cal(int a,int b)
    13 {
    14     return abs(pos[b].first-pos[a].first)+abs(pos[b].second-pos[a].second);
    15 }
    16 
    17 int main()
    18 {
    19     #ifdef DEBUG
    20     freopen("sample.txt","r",stdin);
    21     #endif
    22     
    23     int T;
    24     scanf("%d",&T);
    25     while(T--)
    26     {
    27         int n,m,k;
    28         scanf("%d %d %d %d %d",&n,&m,&pos[0].first,&pos[0].second,&k);//pos[0]是初始位置
    29         for(int i=1;i<=k;i++)
    30         {
    31             int x,y;
    32             scanf("%d %d",&x,&y);
    33             pos[i]=make_pair(x,y);
    34         }
    35         int ans=INF;
    36         memset(dp,INF,sizeof(dp));
    37         for(int i=1;i<=k;i++)
    38             dp[1<<(i-1)][i]=cal(0,i);
    39         for(int s=0;s<(1<<k);s++)
    40         {
    41             for(int i=1;i<=k;i++) //遍历该状态的一个点i作为最后一个经过的点
    42             {
    43                 if(s & (1<<(i-1)))
    44                 {
    45                     for(int j=1;j<=k;j++)//遍历该状态的一个点j作为从j走到i
    46                     {
    47                         if(s & (1<<(j-1)))
    48                             dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+cal(i,j));
    49                     }
    50                 }
    51             }
    52         }
    53         for(int i=1;i<=k;i++)
    54             ans=min(ans,dp[(1<<k)-1][i]+cal(i,0));
    55         printf("The shortest path has length %d
    ",ans);
    56     }
    57     
    58     return 0;
    59 }

     状压DP讲解:https://www.cnblogs.com/Tony-Double-Sky/p/9283254.html

    TSP问题DP详解:https://blog.csdn.net/qq_39559641/article/details/101209534

    关于TSP的一些题:https://blog.csdn.net/yjr3426619/article/details/83387962

    -

  • 相关阅读:
    C语言I博客作业02
    第一次C语言作业
    C语言I博客作业02
    网页常用分享代码
    js生成验证码并验证
    js时间格式的转换
    Git 常用命令
    ASP.NET MVC中使用事务写法
    数据库游标导入数据
    js截取所需字符串长度
  • 原文地址:https://www.cnblogs.com/jiamian/p/12571868.html
Copyright © 2011-2022 走看看