题目
题意: 给定四个数0-9的数,变成另外四个0-9的数。每次可以选择1-4个连续的数,都+1或者都-1 (mod 10).
思路: bfs,搜索从0000到其他状态的最短路。然后哩,我们可以发现从状态a转移到b,相当于从0000转移到b-a.相当于有个偏移量,直接到a状态了,搜索b-a需要多少步即可。
没想到可以转化成b-a,蚌埠住了。
合法的状态转移我是用dfs,3^4暴搜搜出来的。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e4+10;
int n,m,k,T;
struct node{
int a[4];
};
int a[4];
int dist[10][10][10][10]; //到某个状态的最短路
int add(int x)
{
return (x+1)%n;
}
int sub(int x)
{
return (x-1+n)%n;
}
vector<int> res;
vector<vector<int> > v;
int fa[10];
int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void dfs(int cur)
{
if(cur==4)
{
for(int i=0;i<4;++i) fa[i] = i;
vector<int> t;
int flag = 0;
for(int i=0;i<res.size();++i)
{
if(res[i]!=0)
{
if(res[i]==-1) flag |= 1;
if(res[i]==1) flag |= 2;
t.push_back(i);
}
}
if(flag==3||flag==0) return ;
int tot = t.size();
for(int i=0;i<tot;++i)
{
int l = t[i];
int r = (t[(i+1)%tot]);
if(l+1==r) ;
else continue;
int u = find(l),v = find(r);
if(u!=v)
{
fa[v] = u;
}
}
int all = 0;
for(int i=0;i<tot;++i)
{
if(find(t[i])==t[i]) all++;
}
if(all==1)
{
v.push_back(res);
}
return ;
}
res.push_back(1);
dfs(cur+1);
res.pop_back();
res.push_back(-1);
dfs(cur+1);
res.pop_back();
res.push_back(0);
dfs(cur+1);
res.pop_back();
}
void bfs(int aa,int bb,int cc,int dd)
{
memset(dist,0x3f,sizeof(dist));
queue<node> q;
q.push({aa,bb,cc,dd});
dist[aa][bb][cc][dd] = 0;
int cnt = 0;
while(q.size())
{
node tmp = q.front(); q.pop();
int va[4];
int a[4];
for(int i=0;i<4;++i)
{
a[i] = va[i] = tmp.a[i];
}
for(auto &vv:v)
{
for(int i=0;i<4;++i)
{
va[i] = (a[i]+vv[i]+10)%10;
}
if(dist[va[0]][va[1]][va[2]][va[3]] > dist[a[0]][a[1]][a[2]][a[3]] + 1)
{
dist[va[0]][va[1]][va[2]][va[3]] = dist[a[0]][a[1]][a[2]][a[3]] + 1;
q.push({va[0],va[1],va[2],va[3]});
}
// if(va[0]==2&&va[1]==2&&va[2]==8&&va[3]==8)
// {
// cout<<dist[va[0]][va[1]][va[2]][va[3]]<<"??\n";
// for(int i=0;i<4;++i) cout<<a[i]<<" "; cout<<"?\n";
// }
}
}
}
void solve()
{
node t1,t2;
for(int i=0;i<4;++i)
{
scanf("%1d",&t1.a[i]);
}
for(int i=0;i<4;++i)
{
scanf("%1d",&t2.a[i]);
t2.a[i] = (t2.a[i] - t1.a[i] + 10) % 10;
// cout<<i<<":"<<t2.a[i]<<"\n";
}
int ans = dist[t2.a[0]][t2.a[1]][t2.a[2]][t2.a[3]];
printf("%d\n",ans);
}
signed main(void)
{
v.push_back({0,0,0,0});
dfs(0);
// for(auto &vv:v)
// {
// for(auto &item:vv) cout<<item<<" ";
// cout<<"\n";
// }
// n = 10;
bfs(0,0,0,0);
scanf("%d",&T);
while(T--)
solve();
return 0;
} ```