[链接](https://ac.nowcoder.com/acm/contest/51958/D
题意为 有T组循环测试用例,每次给出a,b,c,d四个数字,找出在操作后a+b+c+d的最小操作次数。
操作为:(初始值为10)
将一种资源增加/减少 1 单位
将一种资源增加/减少 10 单位
将一种资源增加/减少 100 单位
将一种资源增加到上限,每种资源的上限都是 300 单位
将一种资源减少到下限,每种资源的下限都是 10 单位
题解:
本题采用了bfs算法。根节点为10,因为每次都会进行8次操作(+1,-1.......)。所以每个点都需要添加8条边,需要加一个条件判断是否超范围。然后进行bfs,用dist[N]记录最小操作次数,从10号点开始循环,每次添加8条点(最多),添加的点的操作次数 = dist[10]+1。如果st[i]==true,代表当前点已经确定了最小操作次数,不会再进入队列。
代码如下
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <math.h>
#include <string>
#define PI 3.14159
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
const int MAX_INT = 0x3f3f3f3f;
const int N = 1e5+15;
const int mod = 1e9+7;
int h[N],e[N],ne[N],dit=1;
bool st[N];
int dist[N];
queue<int> alls;
int a,b,c,d;
void bfs()
{
while(alls.size()!=0)
{
int t = alls.front();
alls.pop();
for(int i = h[t];i!=-1;i=ne[i])
{
int j = e[i];
if(st[j]==false)
{
st[j] = true;
alls.push(j);
dist[j] = min(dist[j],dist[t]+1);
if(st[a]==1 && st[b]==1 && st[c]==1 && st[d]==1)return;
}
}
}
}
void add(int u,int v)
{
if( v>=10 && v<=300)
{
e[dit] = v;
ne[dit] = h[u];
h[u] = dit++;
}
}
void solve()
{
memset(h,-1,sizeof h);
memset(dist,0x3f,sizeof dist);
for(int i=10;i<=300;i++)
{
add(i,i+1);
add(i,i-1);
add(i,i+10);
add(i,i-10);
add(i,i+100);
add(i,i-100);
add(i,300);
add(i,10);
}
alls.push(10);
st[10]=true;
dist[10]=0;
bfs();
int T;
cin>>T;
while(T--)
{
cin>>a>>b>>c>>d;
cout<<dist[a]+dist[b]+dist[c]+dist[d]<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
solve();
}