CF1065D Three Pieces (多元最短路)
题目大意:给你一个棋盘,你需要控制棋子依次经过编号为1~n的所有点,棋子的可以是车,马,象,都依照国际象棋的行棋方式,每走一步消耗1单位时间,但每次更换棋子都需要额外1单位时间,求经过所有点需要的最少时间 ,如果多种方案需要的最少时间相同,输出更换棋子次数最少的那个
有的机房老人用了记忆化搜索,但写起来好像很蛋疼。神仙学弟phy想了一个多元最短路,简洁好写
每个点有三种状态,先暴力建边。
然后根据点的编号从小到大,以每个点为源点跑一次两元最短路
注意,不能在每个点都记录超级源点/汇点,因为这样做会让更换棋子的步骤失效!
所以,每当跑完某个点的最短路时,先记录当前下一个点的三种状态的花费,从下一个编号的点开始跑时,先清数组,再把上次记录的花费扔到起始状态里,再去跑这个点为源点的最短路
接下来就是多元最短路了,可以用重载运算符,比较好写
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 15
#define M 500
#define inf 66666666
using namespace std; int n,cte,num;
int mp[N][N],id[N][N][],head[M];
int px[M],py[M];
struct node{int d,w;
friend bool operator < (const node &s1,const node &s2){
if(s1.d!=s2.d) return s1.d<s2.d;
else return s1.w<s2.w;
}node(int d,int w):d(d),w(w){} node(){}
};
struct Edge{int to,nxt,d,w;}edge[M*];
void ae(int u,int v,int d,int w){
cte++;edge[cte].to=v,edge[cte].nxt=head[u];
edge[cte].d=d,edge[cte].w=w,head[u]=cte;
}
inline int check(int x,int y)
{return <=x&&x<=n&&<=y&&y<=n;}
void Build_Edge()
{
int s0,s1,s2,s3,t1,t2,t3;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
s1=id[i][j][],s2=id[i][j][],s3=id[i][j][];
ae(s1,s2,,),ae(s2,s1,,),ae(s1,s3,,),ae(s3,s1,,),ae(s2,s3,,),ae(s3,s2,,);
for(int x=;x<=n;x++){if(!check(i+x,j))break;t1=id[i+x][j][],ae(s1,t1,,);}
for(int x=;x<=n;x++){if(!check(i,j+x))break;t1=id[i][j+x][],ae(s1,t1,,);}
for(int x=;x<=n;x++){if(!check(i-x,j))break;t1=id[i-x][j][],ae(s1,t1,,);}
for(int x=;x<=n;x++){if(!check(i,j-x))break;t1=id[i][j-x][],ae(s1,t1,,);} for(int x=;x<=n;x++){if(!check(i+x,j+x))break;t3=id[i+x][j+x][],ae(s3,t3,,);}
for(int x=;x<=n;x++){if(!check(i-x,j+x))break;t3=id[i-x][j+x][],ae(s3,t3,,);}
for(int x=;x<=n;x++){if(!check(i+x,j-x))break;t3=id[i+x][j-x][],ae(s3,t3,,);}
for(int x=;x<=n;x++){if(!check(i-x,j-x))break;t3=id[i-x][j-x][],ae(s3,t3,,);} if(check(i+,j+))t2=id[i+][j+][],ae(s2,t2,,);
if(check(i+,j+))t2=id[i+][j+][],ae(s2,t2,,);
if(check(i-,j-))t2=id[i-][j-][],ae(s2,t2,,);
if(check(i-,j-))t2=id[i-][j-][],ae(s2,t2,,);
if(check(i+,j-))t2=id[i+][j-][],ae(s2,t2,,);
if(check(i+,j-))t2=id[i+][j-][],ae(s2,t2,,);
if(check(i-,j+))t2=id[i-][j+][],ae(s2,t2,,);
if(check(i-,j+))t2=id[i-][j+][],ae(s2,t2,,);
} }
node dis[M],lst[];int use[M];
node SPFA()
{
int s1,s2,s3,t1,t2,t3;
queue<int>q;node tmp;
for(int i=;i<n*n;i++)
{
memset(dis,0x3f,sizeof(dis));
memset(use,,sizeof(use));
s1=id[px[i]][py[i]][];
s2=id[px[i]][py[i]][];
s3=id[px[i]][py[i]][];
dis[s1]=lst[],dis[s2]=lst[],dis[s3]=lst[];
use[s1]=,use[s2]=,use[s3]=;
q.push(s1),q.push(s2),q.push(s3);
while(!q.empty())
{
int x=q.front();q.pop();
tmp=dis[x];
for(int j=head[x];j;j=edge[j].nxt){
int v=edge[j].to;
tmp.d+=edge[j].d,tmp.w+=edge[j].w;
if(tmp<dis[v]){ dis[v]=tmp;
if(!use[v]) use[v]=,q.push(v);
}tmp=dis[x];
}use[x]=;
}
t1=id[px[i+]][py[i+]][];
t2=id[px[i+]][py[i+]][];
t3=id[px[i+]][py[i+]][];
lst[]=dis[t1],lst[]=dis[t2],lst[]=dis[t3];
}
node ret;ret.d=inf,ret.w=inf;
s1=id[px[n*n]][py[n*n]][];
s2=id[px[n*n]][py[n*n]][];
s3=id[px[n*n]][py[n*n]][];
if(dis[s1]<ret) ret=dis[s1];
if(dis[s2]<ret) ret=dis[s2];
if(dis[s3]<ret) ret=dis[s3];
return ret;
} int main()
{
//freopen("t1.in","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
scanf("%d",&mp[i][j]),id[i][j][]=++num,id[i][j][]=++num,
id[i][j][]=++num,px[mp[i][j]]=i,py[mp[i][j]]=j;
Build_Edge();
node ret=SPFA();
printf("%d %d\n",ret.d,ret.w);
return ;
}
CF1065D Three Pieces (多元最短路)的更多相关文章
- Codeforces 938 D. Buy a Ticket (dijkstra 求多元最短路)
题目链接:Buy a Ticket 题意: 给出n个点m条边,每个点每条边都有各自的权值,对于每个点i,求一个任意j,使得2×d[i][j] + a[j]最小. 题解: 这题其实就是要我们求任意两点的 ...
- CF1065D Three Pieces
题目描述:给出一个n*n的棋盘,棋盘上每个格子有一个值.你有一个子,要求将这个子从1移到n*n(去k时可以经过比k大的点). 开局时它可以作为车,马,相(国际象棋).每走一步耗费时间1.你也可以中途将 ...
- HDU 2544 最短路 http://acm.hdu.edu.cn/showproblem.php?pid=2544
//代码: //方法1:Dijkstra's Algorithm #include<stdio.h> #include<math.h> #include<string.h ...
- poj 1125 Stockbroker Grapevine(最短路 简单 floyd)
题目:http://poj.org/problem?id=1125 题意:给出一个社交网络,每个人有几个别人可以传播谣言,传播谣言需要时间.问要使得谣言传播的最快,应该从那个人开始传播谣言以及使得所有 ...
- Floyd —Warshall(最短路及其他用法详解)
一.多元最短路求法 多元都求出来了,单源的肯定也能求. 思想是动态规划的思想:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B.所以,我们假设Dis(A ...
- NOIP2016参赛总结
NOIP2016复赛参赛总结 noip2016终于结束了,对于这次的比赛我只想说,死得好惨.(画风突变) 赛前趁着期中考浪到常州去培训,一天两套模拟的训练真的是心力交瘁(好吧没这么严重),不过那些模拟 ...
- Codeforces 196E Opening Portals MST (看题解)
Opening Portals 我们先考虑如果所有点都是特殊点, 那么就是对整个图求个MST. 想在如果不是所有点是特殊点的话, 我们能不能也 转换成求MST的问题呢? 相当于我们把特殊点扣出来, 然 ...
- GDOI2018 新的征程
看标题您一定以为考得很好.. Bad ending.想看美好结局的出门右转其他大佬博客. Day0 早上去车站的时候心情挺好.倒不是因为自己做足了准备,也不是因为预感到有好事发生,而是心情不好也没有用 ...
- [WC2015]未来程序(提交答案)
sub1:ans=a*b%c,龟速乘即可. #include <stdio.h> #include <stdlib.h> unsigned long long a, b, c, ...
随机推荐
- CentOS 6.5下部署日志服务器 Rsyslog+LogAnalyzer+MySQL
简介 LogAnalyzer 是一款syslog日志和其他网络事件数据的Web前端.它提供了对日志的简单浏览.搜索.基本分析和一些图表报告的功能.数据可以从数据库或一般的syslog文本文件中获取,所 ...
- Layui表格编辑【不依赖Layui的动态table加载】
依赖jquer,layui/css <td class="My_edit"></td> Jquery代码 //-----[Layui表格编辑(<td ...
- (56) 解决字段设为readonly无法保存
问题描述:当一个字段设为readonly =True 后,在form表单,即使你用onchange方法改变了值但也不能保存到数据库当时.平时在这样的要求,form表单有些字段要展示给用户,但又要达到不 ...
- python 面向对象 类的内置方法
判断是不是类cls的对象 class A: pass a = A() print(isinstance(a,A)) 判断类sub是不是super的子类 class A: pass class B(A) ...
- C/s模式与B/S模式
C/S模式事是client/server,即客服端/服务模式
- 极路由4pro(HC5962)设置阿里云DDNS
v2ex有个帖子说用Dnspod的API可以一行搞定,不过我既然买的是阿里云的域名还是想尽量用阿里云的API,感觉比较安全,另外修改解析记录后也会自动发邮件通知,所以还是调用阿里云的API吧.阿里云的 ...
- java语言MySQL批处理
本质来讲就是使用Statement和PreStatement的addBatch()方法 代码 import java.sql.*; public class GetConnection{ public ...
- [Javascirpt] Developer-friendly Flow Charts with flowchart.js
Flowchart.js is a great tool for creating quick, simple flowcharts in a way that keeps you out of a ...
- Swift的构造和析构过程
构造过程 Swift的构造过程通过定义构造器来实现. 只是与Objective-C不同的是,Swift的构造器不须要返回值,相同也不须要表明Func. 另外值得提的是,当构造器中为存储型属性赋值时.不 ...
- atitit。流程图的设计与制作 attilax 总结
atitit.流程图的设计与制作 attilax 总结 1. 流程图的规范1 2. 画图语言2 2.1. atitit.CSDN-markdown编辑器2 2.2. js-sequence-diagr ...