题目大意:给你一个棋盘,你需要控制棋子依次经过编号为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 (多元最短路)的更多相关文章

  1. Codeforces 938 D. Buy a Ticket (dijkstra 求多元最短路)

    题目链接:Buy a Ticket 题意: 给出n个点m条边,每个点每条边都有各自的权值,对于每个点i,求一个任意j,使得2×d[i][j] + a[j]最小. 题解: 这题其实就是要我们求任意两点的 ...

  2. CF1065D Three Pieces

    题目描述:给出一个n*n的棋盘,棋盘上每个格子有一个值.你有一个子,要求将这个子从1移到n*n(去k时可以经过比k大的点). 开局时它可以作为车,马,相(国际象棋).每走一步耗费时间1.你也可以中途将 ...

  3. HDU 2544 最短路 http://acm.hdu.edu.cn/showproblem.php?pid=2544

    //代码: //方法1:Dijkstra's Algorithm #include<stdio.h> #include<math.h> #include<string.h ...

  4. poj 1125 Stockbroker Grapevine(最短路 简单 floyd)

    题目:http://poj.org/problem?id=1125 题意:给出一个社交网络,每个人有几个别人可以传播谣言,传播谣言需要时间.问要使得谣言传播的最快,应该从那个人开始传播谣言以及使得所有 ...

  5. Floyd —Warshall(最短路及其他用法详解)

    一.多元最短路求法 多元都求出来了,单源的肯定也能求. 思想是动态规划的思想:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B.所以,我们假设Dis(A ...

  6. NOIP2016参赛总结

    NOIP2016复赛参赛总结 noip2016终于结束了,对于这次的比赛我只想说,死得好惨.(画风突变) 赛前趁着期中考浪到常州去培训,一天两套模拟的训练真的是心力交瘁(好吧没这么严重),不过那些模拟 ...

  7. Codeforces 196E Opening Portals MST (看题解)

    Opening Portals 我们先考虑如果所有点都是特殊点, 那么就是对整个图求个MST. 想在如果不是所有点是特殊点的话, 我们能不能也 转换成求MST的问题呢? 相当于我们把特殊点扣出来, 然 ...

  8. GDOI2018 新的征程

    看标题您一定以为考得很好.. Bad ending.想看美好结局的出门右转其他大佬博客. Day0 早上去车站的时候心情挺好.倒不是因为自己做足了准备,也不是因为预感到有好事发生,而是心情不好也没有用 ...

  9. [WC2015]未来程序(提交答案)

    sub1:ans=a*b%c,龟速乘即可. #include <stdio.h> #include <stdlib.h> unsigned long long a, b, c, ...

随机推荐

  1. zabbix-agent端自定义监控项(free -m)服务器内存使用率

    Agent端操作 [root@agent ~]# vim /usr/local/zabbix/etc/zabbix_agentd.conf 末行追加 UserParameter=memory_user ...

  2. 如何使用图形界面Webmin管理linux服务器

    出处:http://linux.cn/thread/11992/1/1/ 如何使用图形界面Webmin管理linux服务器 一台典型的linux服务器运行命令行环境中,并已经包括了一些用于安装和配置各 ...

  3. ZOJ 3203 Light Bulb( 三分求极值 )

    链接:传送门 题意: 求影子长度 L 的最大值 思路:如果 x = 0 ,即影子到达右下角时,如果人继续向后走,那么影子一定是缩短的,所以不考虑这种情况.根据图中的辅助线外加相似三角形定理可以得到 L ...

  4. [读书笔记] R语言实战 (十三) 广义线性模型

    广义线性模型扩展了线性模型的框架,它包含了非正态的因变量分析 广义线性模型拟合形式: $$g(\mu_\lambda) = \beta_0 + \sum_{j=1}^m\beta_jX_j$$ $g( ...

  5. myeclipse 字体设置为UTF-8

    将myeclipse设置成utf-8格式的方式如下: 1.windows->Preferences打开"首选项"对话框,如图: 2.点击左侧导航树,导航到general-&g ...

  6. js Math常用方法

    ------------------------ 向上取整,有小数就整数部分加1 Math.ceil(5/2) ------------------------ 四舍五入. Math.round(5/ ...

  7. ASP.NET--Attribute定义及用法

    1.Attribute定义 公共语言运行时允许添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法和属性等.Attributes和Microsoft .N ...

  8. 浅析Mysql InnoDB存储引擎事务原理

    浅析Mysql InnoDB存储引擎事务原理 大神:http://blog.csdn.net/tangkund3218/article/details/47904021

  9. 前端project师养成记:开发环境搭建(Sublime Text必备插件推荐)

    为了让自己更像一个前端project师,决定从开发环境開始武装自己. 本文将介绍前段project师开发的一些利器的安装步骤,主要包含了: 1.Node.js的安装 2.Grunt的安装及经常使用插件 ...

  10. Android使用有道翻译API实如今线翻译功能

    在Android应用中,加入在线翻译的功能,这里调用的是有道翻译的API. 使用有道翻译API.首先要申请一个key,申请地址为:path=data-mode">有道翻译API申请地址 ...