D. Three Pieces

题意:

给你一n*n的矩阵,每个格子都有一个数字且所有数字构成一个1~n²的全排列,一开始你的棋子在编号为1的点上,之后你要依次到达编号为2的点、编号为3的点…… 编号为n²的点,移动规则如下

  • 你有三种不同的棋子:①马(走日字)②皇后(到达同一斜线的任何地方)③车(到达同一行同一列的任何任何地方)
  • 你可以任选一种棋子作为开始
  • 可以花1点代价更换当前棋子
  • 可以花1点代价按照当前棋子规则移动一步
  • 从编号为i的格子到达编号为i+1的格子的过程中,可以经过任何其他格子,但是不能走出边界

求出最小代价,以及最小代价下最少换多少次棋子(尽可能少换棋子)

思路:

提供一个O(n²m)复杂度的方法,不需要BFS,n=100都能轻松解决,其中m为换棋子的次数(当n=10时m不会超过15,非常小)

其实依赖于另一个问题:

给你一个n*n的棋盘(n≥3),按马的走法从(x,y)走到(x', y')至少需要多少步,中途不能离开棋盘

代码如下(其中x, y是起点,ex, ey是终点):

int Jud(int x, int y, int ex, int ey)
{if((Check(x, y) || Check(ex, ey)) && abs(ex-x)==1 && abs(ey-y)==1){if(n==3)return 22222222;return 4;}else if(n==4 && Check(x, y) && Check(ex, ey) && abs(ex-x)+abs(ey-y)==3)return 5;else if(n==3 && (abs(ex-x)==0 && abs(ey-y)==2 || abs(ex-x)==2 && abs(ey-y)==0) && !Check(x, y) && !Check(ex, ey))return 4;else{x = abs(x-ex), y = abs(y-ey);if(x<y)swap(x, y);if(x==1 && y==0)return 3;if(x==2 && y==2)return 4;if(x-y<y)return x-y-2*floor((x-2*y)/3.0);elsereturn x-y-2*floor((x-2*y)/4.0);}
}

是的马的最短路问题不需要BFS, 是可以O(1)解决的, 而显然车和象很轻松的也能O(1)解决(注意象有永远到不了的格点)考虑dp[x][y][z]表示当前在编号为x的点上,已经换了y次棋子, 且当前棋子是马/皇后/车的最小代价, 然后就是简单的记忆化搜索了

但是!!这题有个坑,没注意就会各种挂终测,有一种很特殊的情况例如从(1, 1) 走到(9, 8),可以直接换车2步到达,也可以先按马走到(3, 2), 换象之后一步到达(9, 8),所以还需要判一下如果当前是马是否能一步后换象直接到达下一个目标点从而少换一次车!相反同理

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
typedef struct Res
{int x;int y;
}Res;
Res s[200005];
int n, dp[105][18][3], dir[8][2] = {1,-2,-1,2,-1,-2,1,2,2,-1,2,1,-2,-1,-2,1};
int Check(int x, int y)
{if(x==1 && y==1 || x==1 && y==n || x==n && y==1 || x==n && y==n)return 1;return 0;
}
int MtoX(int x, int y, int ex, int ey)
{int i, dx, dy;for(i=0;i<=7;i++){dx = x+dir[i][0];dy = y+dir[i][1];if(dx>=1 && dx<=n && dy>=1 && dy<=n && abs(ex-dx)==abs(ey-dy))return 1;}return 0;
}
int XtoM(int x, int y, int ex, int ey)
{int i, dx, dy;for(i=0;i<=7;i++){dx = ex+dir[i][0];dy = ey+dir[i][1];if(dx>=1 && dx<=n && dy>=1 && dy<=n && abs(x-dx)==abs(y-dy))return 1;}return 0;
}
int Jud(int x, int y, int ex, int ey)
{if((Check(x, y) || Check(ex, ey)) && abs(ex-x)==1 && abs(ey-y)==1){if(n==3)return 22222222;return 4;}else if(n==4 && Check(x, y) && Check(ex, ey) && abs(ex-x)+abs(ey-y)==3)return 5;else if(n==3 && (abs(ex-x)==0 && abs(ey-y)==2 || abs(ex-x)==2 && abs(ey-y)==0) && !Check(x, y) && !Check(ex, ey))return 4;else{x = abs(x-ex), y = abs(y-ey);if(x<y)swap(x, y);if(x==1 && y==0)return 3;if(x==2 && y==2)return 4;if(x-y<y)return x-y-2*floor((x-2*y)/3.0);elsereturn x-y-2*floor((x-2*y)/4.0);}
}
int Sech(int id, int p, int now)
{int ex, ey, x, y;if(dp[id][p][now]!=-1)return dp[id][p][now];if(id==1){dp[id][p][now] = p;return p;}dp[id][p][now] = 22222222;if(p!=0)dp[id][p][now] = min(Sech(id, p-1, 0)+1, min(Sech(id, p-1, 1)+1, Sech(id, p-1, 2)+1));ex = s[id].x, ey = s[id].y;x = s[id-1].x, y = s[id-1].y;if(now==2){if(ex==x || ey==y)dp[id][p][2] = min(dp[id][p][2], Sech(id-1, p, 2)+1);elsedp[id][p][2] = min(dp[id][p][2], Sech(id-1, p, 2)+2);}if(now==1){if(abs(ex-x)==abs(ey-y))dp[id][p][1] = min(dp[id][p][1], Sech(id-1, p, 1)+1);else if((ex+ey)%2==(x+y)%2)dp[id][p][1] = min(dp[id][p][1], Sech(id-1, p, 1)+2);else if(MtoX(x, y, ex, ey) && p!=0)dp[id][p][1] = min(dp[id][p][1], Sech(id-1, p-1, 0)+3);}if(now==0){if(XtoM(x, y, ex, ey) && p!=0)dp[id][p][0] = min(dp[id][p][0], Sech(id-1, p-1, 1)+3);dp[id][p][0] = min(dp[id][p][0], Sech(id-1, p, 0)+Jud(x, y, ex ,ey));}return dp[id][p][now];
}
int main(void)
{int i, j, x, ans, id;scanf("%d", &n);for(i=1;i<=n;i++){for(j=1;j<=n;j++){scanf("%d", &x);s[x].x = i, s[x].y = j;}}ans = 22222222;memset(dp, -1, sizeof(dp));for(i=0;i<=15;i++){if(Sech(n*n, i, 0)<ans){ans = Sech(n*n, i, 0);id = i;}if(Sech(n*n, i, 1)<ans){ans = Sech(n*n, i, 1);id = i;}if(Sech(n*n, i, 2)<ans){ans = Sech(n*n, i, 2);id = i;}}printf("%d %d\n", ans, id);return 0;
}
/*
8
57 45 12 22 16 43 6 29
23 46 48 37 55 1 42 49
59 21 2 8 52 30 51 19
14 18 44 50 34 58 35 53
9 41 13 25 10 62 40 7
47 56 26 15 33 63 31 39
61 38 24 3 27 20 36 28
5 64 11 32 60 54 17 4
*/

Educational Codeforces Round 52: D. Three Pieces(记忆化搜索)相关推荐

  1. Educational Codeforces Round 52: E. Side Transmutations(burnside引理)

    E. Side Transmutations 题意: 给一个字符集A,考虑所有长度为n的字符串S,里面所有的字符都来自于字符集A,再给出m个参数b[1]~b[m],定义一种改变字符串S的操作为按顺序执 ...

  2. codeforces 1089A.lice the Fan(记忆化搜索dp)

    题解:主要在于第五局的时候比赛次数不一样了,所以多开一维专门代表时候打满了5场. dp[0]代表没打满五场,1代表打满了5场] [胜了wa场] [败了wb场] [共赢了na个球] [共输了nb个球]. ...

  3. Educational Codeforces Round 90 (Rated for Div. 2)(A, B, C, D, E)

    Educational Codeforces Round 90 (Rated for Div. 2) Donut Shops 思路 分三种情况: a==c/ba == c / ba==c/b这个时候两 ...

  4. Educational Codeforces Round 24 E. Card Game Again(双指针)

    题目链接:Educational Codeforces Round 24 E. Card Game Again 题意: 给你n个数和一个数k. 现在每次可以拿掉前x个数,后y个数,剩下的数的乘积要能被 ...

  5. Educational Codeforces Round 113 (Rated for Div. 2) ABCD 解题思路

    Educational Codeforces Round 113 (Rated for Div. 2) 经典卡CCC秒DDD,可惜了 怪自己特判写错了吧,对式子找了半天问题结果根本不是式子的问题 A ...

  6. Educational Codeforces Round 112 (Rated for Div. 2)-A. PizzaForces-题解

    目录 Educational Codeforces Round 112 (Rated for Div. 2)-A. PizzaForces Problem Description Input Outp ...

  7. [Educational Codeforces Round 16]A. King Moves

    [Educational Codeforces Round 16]A. King Moves 试题描述 The only king stands on the standard chess board ...

  8. Educational Codeforces Round 114 (Rated for Div. 2) (A ~ F)全题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Educational Codeforces Round 114 (Rated for Div. 2) ...

  9. Educational Codeforces Round 106 (Rated for Div. 2)(A ~ E)题解(每日训练 Day.16 )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 Educational Codeforces Round 106 (Rated for Div. ...

最新文章

  1. python可视化案例书籍推荐_这5款Python可视化神器,总有一款适合你!
  2. pytorch test单张图片_PyTorch版EfficientDet比官方TF实现快25倍?这个GitHub项目数天狂揽千星...
  3. Mybatis中使用Dao实现类实现增删改查【实际开发中使用代理dao】
  4. java如何实现克隆接口_java之实现clone接口的详解,克隆一个对象--对应有浅克隆和深克隆,概念结合代码深入理解...
  5. Android基础巩固进阶
  6. 向量化计算cell_吴恩达老师课程笔记系列第24节-Octave教程之向量化和作业(6)
  7. Django DRF认证组件/权限组件/序列化组件综合总结(完整版)
  8. 每天进步一点点——负载均衡之反向代理
  9. 锚点链接页面元素定位(JQuery)
  10. JavaScript中的Array.prototype.slice.call()方法学习
  11. 免疫算法的c语言,免疫算法(IA)
  12. 在计算机桌面中选择了隐藏如何显示不出来的,电脑桌面文件被隐藏了怎么办
  13. (搬砖)Epic/Feature/Story/Task/Bug到底是什么
  14. dos模拟器即时存档工具_DOS游戏运行模拟器 DOSBox0.72 1.2MB DOS游戏必备
  15. 计算机课代表总结与反思,生物课代表总结与反思(38页)-原创力文档
  16. java eav模式_Magento 2中EAV模型的理解
  17. kali安装步骤失败 选择并安装软件_手机软件安装失败?吉米柚教你几招!
  18. BIOS内部模块详解
  19. 2020 icpc 沈阳
  20. 微信公众号三方平台开发【帐号注册、平台创建】

热门文章

  1. 学python需要什么软件-学python需要什么软件
  2. 学了python能干啥举例-django能干什么
  3. 第I题-生理周期(简单解法跳着试)====人生来就有三个生理周期,分别为体力、感情和智力周期,它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天,
  4. php如何控制用户数,PHP统计当前在线用户数实例讲解
  5. JavaScript的重载和递归
  6. element ui 点击修改开启停用按钮状态
  7. 前端必须掌握30个CSS3选择器
  8. 【java笔记】函数式接口
  9. 【动态规划】状压dp:蓝桥2020补给(旅行商问题)
  10. LAV Filter 源代码分析 2: LAV Splitter