[链接](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();
    
}