题
OvO http://acm.hdu.edu.cn/showproblem.php?pid=6071
2017 Multi-University Training Contest - Team 4 - 1005
解
因为能在2,3之间来回走,所以如果能走T,那么一定能走T+2t(dis[2][3]) (t为自然数)
然后就可以用类似记忆化搜索的方法做
用vis[i][j]表示到达i,走的距离对2*dis[2][3]取模,这个状态是否存在。
(思路来自题解之类的地方)
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
struct node
{
int now;
ll d,dmod;
friend bool operator<(node x,node y) { return x.dmod > y.dmod; }
};
int mod;
priority_queue<node> que;
ll k,dis[5][5];
bool vis[5][60044];
int nxt(int now,int chg){ return ((now+chg-1+4)%4+1); }
void solve()
{
int i,j,u,v;
node q,tmp;
mod=dis[2][3]*2;
ll ans=((k-1)/mod*mod+mod);
memset(vis,0,sizeof(vis));
while(!que.empty())
que.pop();
vis[2][0]=1;
q.now=2; q.d=q.dmod=0;
que.push(q);
while(!que.empty())
{
q=que.top();
que.pop();
if(q.d>ans) break;
u=q.now;
for(i=-1;i<=1;i+=2)
{
v=nxt(u,i);
tmp=q;
tmp.now=v; tmp.d+=(dis[u][v]);
tmp.dmod=tmp.d%mod;
if(tmp.d>=k && tmp.now==2)
{
ans=min(ans,tmp.d);
continue;
}
if(vis[v][tmp.dmod]) continue;
vis[v][tmp.dmod]=1;
if(tmp.d>k) tmp.dmod=tmp.d;
que.push(tmp);
}
}
ll kmod=k%mod;
for(i=0;i<mod;i++)
if(vis[2][i])
ans=min(ans,((k-i-1)/mod+1)*mod+i);
printf("%lld\n",ans);
}
int main()
{
int cas,i,j,a,b;
cin>>cas;
while(cas--)
{
scanf("%lld",&k);
for(i=1;i<=4;i++)
{
a=i; b=nxt(i,1);
scanf("%d",&dis[a][b]);
dis[b][a]=dis[a][b];
}
solve();
}
return 0;
}