Codeforces Gym101502 I.Move Between Numbers-最短路(Dijkstra优先队列版和数组版)
2.0 s
256 MB
standard input
standard output
You are given n magical numbers a1, a2, ..., an, such that the length of each of these numbers is 20 digits.
You can move from the ith number to the jth number, if the number of common digits between ai and aj is exactly 17 digits.
The number of common digits between two numbers x and y is computed is follow:
.
Where countXi is the frequency of the ith digit in the number x, and countYi is the frequency of the ith digit in the number y.
You are given two integers s and e, your task is to find the minimum numbers of moves you need to do, in order to finish at number aestarting from number as.
The first line contains an integer T (1 ≤ T ≤ 250), where T is the number of test cases.
The first line of each test case contains three integers n, s, and e (1 ≤ n ≤ 250) (1 ≤ s, e ≤ n), where n is the number of magical numbers, s is the index of the number to start from it, and e is the index of the number to finish at it.
Then n lines follow, giving the magical numbers. All numbers consisting of digits, and with length of 20 digits. Leading zeros are allowed.
For each test case, print a single line containing the minimum numbers of moves you need to do, in order to finish at number ae starting from number as. If there is no answer, print -1.
1
5 1 5
11111191111191111911
11181111111111818111
11811171817171181111
11111116161111611181
11751717818314111118
3
In the first test case, you can move from a1 to a2, from a2 to a3, and from a3 to a5. So, the minimum number of moves is 3 moves.
这个题的题意没怎么看懂,大体的就是数换位置,如果两个串之间相同的数比较个数(数不一定是连续相同的),把个数小的加起来,正好个数等于17的话,这两个串就建立关系。
然后给你起点和终点,求最少次数(好像),就是迪杰斯特拉跑最短路,然而我写的时候,怎么写都是RE,还是猪队友用他优先队列的板子跑过的.
赛后补题,昨天晚上,一晚上都在杠二维数组存的迪杰斯特拉,还找学长要了学长的板子,都跑不过,一晚上放弃。。今天上午,发现,是初始化没写好,把两份代码的初始化都改好之后都跑过了。。。(MDZZ)
代码1:(队友优先队列版的)
1 //I. Move Between Numbers-和猪一样的过了
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<algorithm>
6 #include<cmath>
7 #include<queue>
8 #include<vector>
9 using namespace std;
10 const int N=1e3+10;
11 const int inf=0x3f3f3f3f;
12 int a[N][N];
13 char ss[N][N];
14 int n; //n个点1~n m 条边 起点 s
15 int d[N],done[N],p[N]; //d[i]表示i点到起点s的最短路距离
16 //done[u]==1表示u点到起点点s的最短路已经找到
17 //p[i]表示起点s到i的最短路径与i点相连的上一条边
18 struct edge //边结构体
19 {
20 int from,to,dis;
21 };
22 vector<edge> edges; //边集 无向图 边数*2
23 vector<int> g[N]; //g数组存的是边的序号
24 struct mindis //压入优先队列的结构体 因为d[u]和u要绑定起来 才可标记 u是否已确定最短路
25 {
26 int d,u;
27 bool operator <(const mindis& rhs)const{
28 return d>rhs.d; //距离最小值优先 距离相等无所谓 随便一个先出 边权是正的 两个会依次访问 不会影想结果
29 }
30 };
31 void init(int n) //每次输入数据清空容器
32 {
33 for(int i=0;i<=n;i++)
34 g[i].clear();
35 edges.clear();
36 }
37 void addedge(int from,int to,int dis) //加边操作
38 {
39 edges.push_back((edge){from,to,dis}); //将边压入边集
40 int k=edges.size();
41 g[from].push_back(k-1); //k-1为边序号 以后调用边集数组要从下标0开始 所以边的编号从0开始 将边序号压入已from为起点的数组
42 }
43 void dijkstra(int s) //主算法
44 {
45 for(int i=0;i<=n;i++) //把距离初始化为 inf 不能用memset 自己估算一下路径最长有多长 inf定义大一点就好
46 d[i]=inf;
47 d[s]=0; //到自己的最短距离直接设为0
48 priority_queue<mindis> q; //优先队列 小顶堆 最小值优先
49 q.push((mindis){0,s});
50 memset(done,0,sizeof(done)); //初始化数组
51 memset(p,-1,sizeof(p));
52 while(!q.empty()) //队列非空
53 {
54 mindis x=q.top(); //取当前最小值
55 q.pop();
56 int u=x.u;
57 if(done[u]==1) //已确定路径直接跳过
58 continue;
59 done[u]=1; //标记 已确定
60 for(int i=0;i<g[u].size();i++)
61 {
62 edge e =edges[g[u][i]]; //g[u][i]表示以u为起点的第i条边在边集edges中的下标
63 if(d[e.to]>d[u]+e.dis) //满足条件更新距离
64 {
65 d[e.to]=d[u]+e.dis;
66 p[e.to]=g[u][i]; //保存路径
67 q.push((mindis){d[e.to],e.to}); //把更新完的值压入队列
68 }
69 }
70 }
71 }
72 int main(){
73 int t,s,e;
74 scanf("%d",&t);
75 while(t--){
76 scanf("%d%d%d",&n,&s,&e);
77 memset(a,0,sizeof(a));
78 for(int i=1;i<=n;i++){
79 cin>>ss[i];
80 for(int j=0;j<20;j++){
81 int temp=ss[i][j]-'0';
82 a[i][temp]++;
83 }
84 }
85 init(n);
86 for(int i=1;i<=n;i++){
87 for(int j=i+1;j<=n;j++){
88 int ret=0;
89 for(int h=0;h<10;h++)
90 ret+=min(a[i][h],a[j][h]);
91 if(ret==17) {
92 int w=1;
93 addedge(i,j,w);
94 addedge(j,i,w);
95 }
96 }
97 }
98 dijkstra(s);
99 if(d[e]==inf)printf("-1\n");
100 else printf("%d\n",d[e]);
101 }
102 return 0;
103 }
代码2:(自己的板子(垃圾板子。。。),二维数组版的)
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<algorithm>
5 #include<cmath>
6 using namespace std;
7 #include<bits/stdc++.h>
8 using namespace std;
9 const int N=1e3+10;
10 const int INF=0x3f3f3f3f;
11 char ss[N][N];
12 int q[N][N];
13 int a[N][N]; //存数据的边
14 int dist[N]; //记录最短路的距离
15 int vis[N]; //标记是否访问过
16 int n,s,e;
17 void Dijkstra(){ //迪杰斯特拉算法
18 int tmp,v;
19 memset(vis,0,sizeof(vis));
20 for(int i=1;i<=n;i++)
21 dist[i]=a[s][i]; //首先将dist初始化,将起点与其他点的距离先存进去
22 dist[s]=0; //起点到起点距离为0
23 vis[s]=1; //标记起点被访问过
24 for(int i=1;i<=n-1;i++){ //这里修改了
25 tmp=INF;
26 for(int j=1;j<=n;j++){ //下面的也修改了
27 if(vis[j]==0&&tmp>dist[j]){ //未访问过并且找出与当前要查找的点的最短路径(因为与某个点相连的其他点有多个,找出距离最短的,所以for循环一遍)
28 tmp=dist[j];
29 v=j; //用v存一下当前的最短路径的点
30 }
31 }
32 vis[v]=1;//将当前找到的点标记访问过
33 for(int l=1;l<=n;l++){
34 if(!vis[l]) //找出与之相连的点的最短路径
35 dist[l]=min(dist[l],dist[v]+a[v][l]);//更新d
36 }
37 }
38 }
39 int main(){
40 int t;
41 scanf("%d",&t);
42 while(t--){
43 scanf("%d%d%d",&n,&s,&e);
44 for(int i=1;i<=n;i++){
45 for(int j=1;j<=n;j++){
46 if(i==j)a[i][j]=0; //这里修改了
47 else a[i][j]=INF;
48 }
49 }
50 memset(q,0,sizeof(q));
51 for(int i=1;i<=n;i++){
52 cin>>ss[i];
53 for(int j=0;j<20;j++){
54 int temp=ss[i][j]-'0';
55 q[i][temp]++;
56 }
57 }
58 for(int i=1;i<=n;i++){
59 for(int j=i+1;j<=n;j++){
60 int ret=0;
61 for(int h=0;h<10;h++)
62 ret+=min(q[i][h],q[j][h]);
63 if(ret==17) a[i][j]=a[j][i]=1;
64 }
65 }
66 Dijkstra();
67 if(dist[e]==INF)printf("-1\n");
68 else printf("%d\n",dist[e]);
69 }
70 return 0;
71 }
代码3:(学长的板子,初始化一开始也有问题。。。)
1 //I-头铁,再来一次-学长的板子,加油啊,大兄弟-死了,头被打爆,还是RE2,过了,初始化的时候错了。。。
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<algorithm>
7 #include<queue>
8 using namespace std;
9 #define MAX 1005
10 const int INF=0x3f3f3f3f;
11 int arc[1005][1005];
12 int d[1005],n,s,e;
13 char ss[MAX][MAX];
14 int q[MAX][MAX];
15 void dijkstra(int s) // 求s 到其他各点的最短路径
16 {
17 int v,w,k,m;
18 int fina[MAX];
19 int p[MAX];
20 memset(fina,0,sizeof(fina));
21 for(v=1;v<=n; v++) //v=1;数组从1开始
22 {
23 d[v] = arc[s][v];
24 }
25 d[s] = 0;
26 fina[s] = 1;
27 for(v=1; v<n; v++)
28 {
29 m = INF;
30 for(w=1; w<=n; w++)
31 {
32 if( fina[w]==0 && d[w]<m )
33 {
34 k = w;
35 m = d[w];
36 }
37 }
38 fina[k] = 1;
39 for(w=1; w<=n; w++)
40 {
41 if( !fina[w]&& (m+arc[k][w] < d[w] ) )
42 {
43 d[w] = m + arc[k][w];
44 p[w] = k;
45 }
46 }
47 }
48 }
49 int main(){
50 int t;
51 scanf("%d",&t);
52 while(t--){
53 scanf("%d%d%d",&n,&s,&e);
54 for(int i=1;i<=n;i++){
55 for(int j=1;j<=n;j++){
56 if(i==j)arc[i][j]=0;
57 else arc[i][j]=INF;
58 }
59 }
60 memset(q,0,sizeof(q));
61 for(int i=1;i<=n;i++){
62 cin>>ss[i];
63 for(int j=0;j<20;j++){
64 int temp=ss[i][j]-'0';
65 q[i][temp]++;
66 }
67 }
68 for(int i=1;i<=n;i++){
69 for(int j=i+1;j<=n;j++){
70 int ret=0;
71 for(int h=0;h<10;h++)
72 ret+=min(q[i][h],q[j][h]);
73 if(ret==17) arc[i][j]=arc[j][i]=1;
74 }
75 }
76 memset(d,0,sizeof(d));
77 dijkstra(s);
78 if(d[e]==INF)printf("-1\n");
79 else printf("%d\n",d[e]);
80 }
81 return 0;
82 }
Codeforces Gym101502 I.Move Between Numbers-最短路(Dijkstra优先队列版和数组版)的更多相关文章
- POJ - 2387 Til the Cows Come Home (最短路Dijkstra+优先队列)
Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before ...
- HDU 1874-畅通project续(最短路Dijkstra+优先队列)
畅通project续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 最短路--dijkstra+优先队列优化模板
不写普通模板了,还是需要优先队列优化的昂 #include<stdio.h> //基本需要的头文件 #include<string.h> #include<queue&g ...
- 最短路 dijkstra 优先队列
1.裸题 hdu2544 http://acm.hdu.edu.cn/showproblem.php?pid=2544 Way1: 好像不对 #include <cstdio> #incl ...
- 最短路 dijkstra+优先队列+邻接表
http://acm.hdu.edu.cn/showproblem.php?pid=2544 #include<iostream> #include<queue> #inclu ...
- Codeforces 385C Bear and Prime Numbers
题目链接:Codeforces 385C Bear and Prime Numbers 这题告诉我仅仅有询问没有更新通常是不用线段树的.或者说还有比线段树更简单的方法. 用一个sum数组记录前n项和, ...
- 2017 JUST Programming Contest 3.0 I. Move Between Numbers
I. Move Between Numbers time limit per test 2.0 s memory limit per test 256 MB input standard input ...
- Codeforces 385C Bear and Prime Numbers(素数预处理)
Codeforces 385C Bear and Prime Numbers 其实不是多值得记录的一道题,通过快速打素数表,再做前缀和的预处理,使查询的复杂度变为O(1). 但是,我在统计数组中元素出 ...
- 【poj 1724】 ROADS 最短路(dijkstra+优先队列)
ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12436 Accepted: 4591 Description N ...
随机推荐
- LeetCode之Weekly Contest 90
LeetCode第90场周赛记录 第一题:亲密字符串 问题: 给定两个由小写字母构成的字符串 A 和 B ,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true :否则返回 ...
- python入门:输出1-10以内除去7的所有数(自写)
#!/usr/bin/env python # -*- coding:utf-8 -*- #输出1-10以内除去7的所有数(自写) """ 变量kaishi赋值等于1,w ...
- python日记整理
都是自己的学习总结,要是总结的有问题大佬麻烦评价一下我好修改,谢谢 python插件插件+pycharm基本用法+markdown文本编写+jupyter notebook的基本操作汇总 一.计算机基 ...
- 科学计算库Numpy——概述
Numpy主要用于数组的各种计算. 导入Numpy import numpy as np 数组类型 Numpy的数组类型为numpy.ndarray. array=np.array([1,2,3,4, ...
- python3 连接 mysql和mariadb的模块
是pymysql python2中是MySQL-python sudo pip install pymysql 参考博客https://www.jb51.net/article/140387.htm
- python输出mssql 查询结果示例
# -*- coding: utf-8 -*-# python 3.6import pymssql conn=pymssql.connect(host='*****',user='******',pa ...
- Thonny -- 简洁的 python 轻量级 IDE
Thonny目前是 树莓派 上 默认的 Python 开发环境. 该 IDE 是 Institute of Computer Science of University of Tartu (爱沙尼亚 ...
- 在SCIKIT中做PCA 逆变换 -- 新旧特征转换
PCA(Principal Component Analysis)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降 ...
- SpringMVC之Controller简单使用
//环境 spring-4.3.18/JDK1.8/开发工具/IntelliJ IDEA 2018.2.5 x64 //工程结构图 //web.xml <?xml version="1 ...
- nw335 debian sid x86-64 -- 1 需求介绍
自己的台式机上面有有线网卡,路由器在客厅,托一条长长的线,关门也不方便.没有选择PCI无线网卡,没有选择nano类型的迷你网卡.买了nw335,带一条5DB天线,信号应该会好点.于是,开始了在debi ...