【记忆化路线】

【记忆化路线】

Spirit of Cola.

https://ac.nowcoder.com/acm/contest/110312/J

注意写法积累!

(1)vector多维数组

//记最短路
vector dp(c[0] + 1, vector(c[1] + 1, vector<int>(c[2] + 1, -1)));
//记路线
vector last(c[0] + 1, vector(c[1] + 1, vector<array<int, 3>>(c[2] + 1, {-1, -1, -1})));

(2)lambda递归输出路线

 auto pr=[&](auto self,int x,int y,int z)->void{
            if(x==w[0] && y==w[1] && z==w[2]) return;
            auto it=last[x][y][z];
            //对自身的递归:self
            self(self,it[0],it[1],it[2]);
            //先递归再输出:从头到尾
            //如果是先输出再递归:从尾到头
            cout<<x<<" "<<y<<" "<<z<<endl;
        };
        pr(pr,pos[0],pos[1],pos[2]);
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef pair<int,int> PII;
typedef long long ll;
ll abss(ll a){return a>0?a:-a;}
ll max_(ll a,ll b){return a>b?a:b;}
ll min_(ll a,ll b){return a<b?a:b;}
bool cmpll(ll a,ll b){return a>b;}
const int INF=0x3f3f3f3f;
const int N=3e2+10;
//BFS最短路+记路线
array<int,3> c,w;
int t;
void solve(){
    cin>>c[0]>>c[1]>>c[2]>>w[0]>>w[1]>>w[2]>>t;

    //记最短路
    vector dp(c[0] + 1, vector(c[1] + 1, vector<int>(c[2] + 1, -1)));
    //记路线
    vector last(c[0] + 1, vector(c[1] + 1, vector<array<int, 3>>(c[2] + 1, {-1, -1, -1})));
    queue< array<int,3> > q;
    dp[w[0]][w[1]][w[2]]=0;
    q.push({w[0],w[1],w[2]});
    while(q.size()){
        auto tt=q.front();
        q.pop();
        //互相倒
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i==j) continue;
                int d=min(tt[i],c[j]-tt[j]);
                auto tmp=tt;
                tmp[i]-=d;
                tmp[j]+=d;
                if(dp[tmp[0]][tmp[1]][tmp[2]]==-1){
                    //记录长度
                    dp[tmp[0]][tmp[1]][tmp[2]]=dp[tt[0]][tt[1]][tt[2]]+1;
                    //记录路线
                    last[tmp[0]][tmp[1]][tmp[2]]=tt;
                    q.push(tmp);
                }
            }
        }
        //倒出最小值
        int minn=1e9;
        //注意这里!如果一个杯子已经倒空->不需要再计算!
        for(int i=0;i<3;i++) if(tt[i]) minn=min(minn,tt[i]);
        for(int i=0;i<3;i++){
            if(tt[i]==minn){
                auto tmp=tt;
                tmp[i]=0;
                if(dp[tmp[0]][tmp[1]][tmp[2]]==-1){
                    //记录长度
                    dp[tmp[0]][tmp[1]][tmp[2]]=dp[tt[0]][tt[1]][tt[2]]+1;
                    //记录路线
                    last[tmp[0]][tmp[1]][tmp[2]]=tt;
                    q.push(tmp);
                }
            }
        }
    }
    //找所有满足条件的最小值
    int cnt=1e9;
    array<int,3> pos;
    for(int i=0;i<=c[0];i++){
        for(int j=0;j<=c[1];j++){
            for(int k=0;k<=c[2];k++){
                if(i==t || j==t || k==t){
                    if(dp[i][j][k]!=-1){
                        if(cnt>dp[i][j][k]){
                            cnt=dp[i][j][k];
                            pos={i,j,k};
                        }
                    }
                }
                //cout<<cnt<<endl;
            }
        }
    }
    if(cnt==1e9){
        cout<<"-1"<<endl;
        return;
    }
    else{
        //输出路线:lambda函数递归(学习!)
        cout<<cnt<<endl;
        auto pr=[&](auto self,int x,int y,int z)->void{
            if(x==w[0] && y==w[1] && z==w[2]) return;
            auto it=last[x][y][z];
            //对自身的递归:self
            self(self,it[0],it[1],it[2]);
            //先递归再输出:从头到尾
            //如果是先输出再递归:从尾到头
            cout<<x<<" "<<y<<" "<<z<<endl;
        };
        pr(pr,pos[0],pos[1],pos[2]);
    }
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--) solve();
    return 0;
}
posted @ 2025-05-18 19:04  White_ink  阅读(2)  评论(0)    收藏  举报