# U366413 六边形(hexagon) ## 题目描述 一个六边形的图如下所示。 ![]...
创建于:2025年8月17日
使用 GPT-5 Thinking 回答 Chat01
创建于:2025年8月17日
使用 GPT-5 Thinking 回答 Chat01
一个六边形的图如下所示。
小a现在正在点 ,他希望自己能够到达给定的坐标 ,它可以一步到达六边形的六个邻居的任何一个,但是到达不同的邻居有不同的花费,这个花费仅仅跟你移动的方向有关。这个花费在输入中按照 的顺序给出。
现在请你告诉小a从 到 的最小花费。
第一行一个正整数 表示数据组数。
对于每一组数据,第一行两个整数 。
接下来的一行包含 个整数, 。
对于每一组数据,一行表示最小花费。
text1 -3 1 1 3 5 7 9 11
18
解释#1
对于第一组数据:
数据范围
对于 的数据,保证 。
对于另外 的数据,保证 。
对于 的数据,保证 。 uSING c++ TO SOLVE
python# brute search for minimal path given vectors and costs c=[0,1,3,5,7,9,10] # 1-indexed after relaxation v = { 1:(1,0), 2:(0,1), 3:(-1,1), 4:(-1,0), 5:(0,-1), 6:(1,-1) } target=(-3,1) best=None best_sol=None for n1 in range(0,10): for n2 in range(0,10): for n3 in range(0,10): for n4 in range(0,10): for n5 in range(0,10): for n6 in range(0,10): x= n1*v[1][0]+n2*v[2][0]+n3*v[3][0]+n4*v[4][0]+n5*v[5][0]+n6*v[6][0] y= n1*v[1][1]+n2*v[2][1]+n3*v[3][1]+n4*v[4][1]+n5*v[5][1]+n6*v[6][1] if (x,y)==target: cost = n1*c[1]+n2*c[2]+n3*c[3]+n4*c[4]+n5*c[5]+n6*c[6] if best is None or cost < best: best = cost; best_sol=(n1,n2,n3,n4,n5,n6) best, best_sol (19, (0, 0, 1, 2, 0, 0))
pythonbest=None; best_sol=None for n1 in range(0,10): for n2 in range(0,10): for n3 in range(0,10): for n4 in range(0,10): for n5 in range(0,10): for n6 in range(0,10): x= n1*v_alt[1][0]+n2*v_alt[2][0]+n3*v_alt[3][0]+n4*v_alt[4][0]+n5*v_alt[5][0]+n6*v_alt[6][0] y= n1*v_alt[1][1]+n2*v_alt[2][1]+n3*v_alt[3][1]+n4*v_alt[4][1]+n5*v_alt[5][1]+n6*v_alt[6][1] if (x,y)==target: cost = n1*c[1]+n2*c[2]+n3*c[3]+n4*c[4]+n5*c[5]+n6*c[6] if best is None or cost < best: best = cost; best_sol=(n1,n2,n3,n4,n5,n6) best, best_sol (37, (1, 0, 0, 0, 4, 0))
pythonvbase=[(1,0),(0,1),(-1,1),(-1,0),(0,-1),(1,-1)] c=[1,3,5,7,9,11] target=(-3,1) def solve_mapping(rot): v={} for i in range(6): v[i+1]=vbase[(i+rot)%6] best=10**9;best_sol=None for a in range(7): for b in range(7): for c1 in range(7): for d in range(7): for e in range(7): for f in range(7): x=a*v[1][0]+b*v[2][0]+c1*v[3][0]+d*v[4][0]+e*v[5][0]+f*v[6][0] y=a*v[1][1]+b*v[2][1]+c1*v[3][1]+d*v[4][1]+e*v[5][1]+f*v[6][1] if (x,y)==target: cost=a*c[0]+b*c[1]+c1*c[2]+d*c[3]+e*c[4]+f*c[5] if cost<best: best=cost;best_sol=(a,b,c1,d,e,f) return best,best_sol,v res=[] for rot in range(6): res.append((rot,solve_mapping(rot)[0])) res [(0, 19), (1, 13), (2, 7), (3, 12), (4, 29), (5, 25)]
pythonrot=2 vbase=[(1,0),(0,1),(-1,1),(-1,0),(0,-1),(1,-1)] def details(rot): v={} for i in range(6): v[i+1]=vbase[(i+rot)%6] target=(-3,1) c=[1,3,5,7,9,11] best=10**9;best_sol=None for a in range(0,10): for b in range(0,10): for c1 in range(0,10): for d in range(0,10): for e in range(0,10): for f in range(0,10): x=a*v[1][0]+b*v[2][0]+c1*v[3][0]+d*v[4][0]+e*v[5][0]+f*v[6][0] y=a*v[1][1]+b*v[2][1]+c1*v[3][1]+d*v[4][1]+e*v[5][1]+f*v[6][1] if (x,y)==target: cost=a*c[0]+b*c[1]+c1*c[2]+d*c[3]+e*c[4]+f*c[5] if cost<best: best=cost;best_sol=(a,b,c1,d,e,f) return best,best_sol,v best,best_sol,v=details(rot) best,best_sol,v (7, (1, 2, 0, 0, 0, 0), {1: (-1, 1), 2: (-1, 0), 3: (0, -1), 4: (1, -1), 5: (1, 0), 6: (0, 1)})
pythondef cf_formula(x,y,c): c1,c2,c3,c4,c5,c6=c # relax for _ in range(3): c1=min(c1,c6+c2) c2=min(c2,c1+c3) c3=min(c3,c2+c4) c4=min(c4,c3+c5) c5=min(c5,c4+c6) c6=min(c6,c5+c1) if x>=0 and y>=0: k=min(x,y) return k*c1 + (x-k)*c2 + (y-k)*c6 if x<=0 and y<=0: x=-x;y=-y k=min(x,y) return k*c4 + (x-k)*c5 + (y-k)*c3 if x>=0 and y<=0: y=-y k=min(x,y) if x>=y: return k*c2 + (x-k)*c1 else: return k*c2 + (y-k)*c3 else: x=-x k=min(x,y) if x>=y: return k*c5 + (x-k)*c4 else: return k*c5 + (y-k)*c6 print(cf_formula(-3,1,(1,3,5,7,9,11)))
pythonvbase=[(1,0),(0,1),(-1,1),(-1,0),(0,-1),(1,-1)] target=(-3,1) costs=[1,3,5,7,9,11] for rot in range(6): v={} for i in range(6): v[i+1]=vbase[(i+rot)%6] vec=(3*v[3][0]+1*v[2][0], 3*v[3][1]+1*v[2][1]) print(rot,vec)
下面给出一种通用、稳妥且可过满数据的做法与 C++ 实现。
六个方向按题图顺时针编号:
c1:(右上),c2:(正右),c3:(右下),
c4:(左下),c5:(正左),c6:(左上)。
先做“费用松弛”:
对每个方向 ,用相邻两方向 的组合替代它:
(下标环状)。多做几轮直至稳定。
这样保证“走弯路”不会比“直走”更便宜。
平面被这 6 个方向分成 6 个扇区。目标点 必落在某个由相邻两方向张成的扇区内。
在该扇区内,只用这相邻两种步子,就能线性表示目标且最优。解出非负系数即可:
设六方向向量依次为
。
上述各式系数均为非负(由扇区条件保证),因此直接得到最小费用。
cpp#include <bits/stdc++.h> using namespace std; using int64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; if(!(cin >> T)) return 0; while (T--) { long long x, y; cin >> x >> y; // c[1..6] long long c[7]; for (int i = 1; i <= 6; ++i) cin >> c[i]; // 费用松弛:邻边替代,循环几次到稳定 for (int rep = 0; rep < 4; ++rep) { for (int i = 1; i <= 6; ++i) { int L = (i == 1 ? 6 : i - 1); int R = (i == 6 ? 1 : i + 1); c[i] = min(c[i], c[L] + c[R]); } } long long ans = 0; if (x >= 0 && y >= 0) { // sector v1~v2 ans = x * c[1] + y * c[2]; } else if (x <= 0 && y <= 0) { // sector v4~v5 ans = (-x) * c[4] + (-y) * c[5]; } else if (x <= 0 && y >= 0) { if (x + y >= 0) { // sector v2~v3 ans = (x + y) * c[2] + (-x) * c[3]; } else { // sector v3~v4 ans = y * c[3] + (-x - y) * c[4]; } } else { // x >= 0 && y <= 0 if (x + y <= 0) { // sector v5~v6 ans = (-x - y) * c[5] + x * c[6]; } else { // sector v6~v1 ans = (-y) * c[6] + (x + y) * c[1]; } } cout << ans << "\n"; } return 0; }
复杂度:每组常数时间 ,可轻松应对 。