codeforces 8c Looking for Order

Posted Omz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 8c Looking for Order相关的知识,希望对你有一定的参考价值。

https://vjudge.net/problem/CodeForces-8C

题意:

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

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

思路:

由于数据范围比较小,所以可以考虑用状压dp来写。由于每次拿东西之后都要返回起点,那么其实拿东西的顺序是没有影响的,所以利用题目给定的顺序进行剪枝,即每次进行扩展的时候都考虑在前面的点已经取完了。

然后每次记录的时候,非常巧妙的方法,如果一个点的话,直接记录这个点,如果有两个点的话,那么就用(i+1)*100 + (j+1)来记录,因为点数最多时只有24,输出的时候递归输出就行了,递归输出这里还是比较巧妙的。

代码:(有详细的注释)

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <vector>
  4 using namespace std;
  5 
  6 struct node
  7 {
  8     int x,y;
  9 } a[30];
 10 
 11 int mp[30][30];
 12 vector<int> ans;
 13 
 14 int cal(int i,int j)
 15 {
 16     return (a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y);
 17 }
 18 
 19 const int maxn = (1 << 24)+2;
 20 const int gg = 0x3f3f3f3f;
 21 
 22 int dp[maxn],last[maxn],rec[maxn];
 23 
 24 void output(int s)
 25 {
 26     if (~last[s])
 27         output(last[s]);//递归输出
 28 
 29     if (rec[s])
 30     {
 31         if (rec[s] > 100) ans.push_back(rec[s] / 100);//第一个扩展的点
 32 
 33         ans.push_back(rec[s] % 100);
 34         ans.push_back(0);//每次都要返回起点
 35     }
 36 }
 37 
 38 int main()
 39 {
 40     int n;
 41 
 42     node tmp;
 43 
 44     scanf("%d%d",&tmp.x,&tmp.y);
 45 
 46     scanf("%d",&n);
 47 
 48     for (int i = 0;i < n;i++)
 49     {
 50         scanf("%d%d",&a[i].x,&a[i].y);
 51     }
 52 
 53     a[n] = tmp;
 54 
 55     for (int i = 0;i <= n;i++)
 56         for (int j = i + 1;j <= n;j++)
 57         mp[i][j] = mp[j][i] = cal(i,j);
 58 
 59     memset(dp,gg,sizeof(dp));
 60     memset(last,-1,sizeof(last));
 61 
 62     dp[0] = 0;
 63 
 64     for (int s = 0;s < (1<<n);s++)
 65     {
 66         if (dp[s] >= gg) continue;
 67 
 68         for (int i = 0;i < n;i++)
 69         {
 70             if (((1 << i) & s) == 0)//这个点没有被走过
 71             {
 72                 int val = dp[s] + mp[n][i] * 2;
 73 
 74                 if (dp[s|(1 << i)] > val)
 75                 {
 76                     dp[s|(1 << i)] = val;
 77                     last[s|(1 << i)] = s;//记录前驱,下同
 78                     rec[s|(1 << i)] = i+1;
 79                 }
 80 
 81                 for (int j = i + 1;j < n;j++)//从i+1开始枚举保证了不会有重复情况
 82                 {
 83                     if (((1<<j)&s) == 0)
 84                     {
 85                         int tmp = dp[s] + mp[n][i] + mp[i][j] + mp[j][n];
 86 
 87                         if (dp[s|(1<<i)|(1<<j)] > tmp)
 88                         {
 89                             dp[s|(1<<i)|(1<<j)] = tmp;
 90                             last[s|(1<<i)|(1<<j)] = s;
 91                             rec[s|(1<<i)|(1<<j)] = (i+1) * 100 + (j+1);//巧妙的记录
 92                         }
 93                     }
 94                 }
 95 
 96                 break;//强行顺序剪枝
 97             }
 98         }
 99 
100         //printf("%d\n",dp[s]);
101     }
102 
103 
104     ans.clear();
105 
106     output((1<<n)-1);
107 
108     printf("%d\n",dp[(1<<n)-1]);
109 
110     printf("0 ");
111 
112     for (int i = 0;i < ans.size();i++)
113         printf("%d%s",ans[i],i == ans.size() - 1 ? "\n" :" ");
114 
115     return 0;
116 }

 

以上是关于codeforces 8c Looking for Order的主要内容,如果未能解决你的问题,请参考以下文章

CF8C Looking for Order 题解

Are you looking for new shoes this year 7.25

Tech town or hive of history? Looking for the real Wuzhen

Error: No EPCS layout data - looking for section [EPCS-C84018]

CodeforcesCF 8 C Looking for Order(状压dp)

安装mysql-5.7.17cmke报错