1.非常可乐
思路,用到BFS,6个方向搜索,S-A,A-S,S-B,B-S,A-B,B-A;
-
f[i][j][k]代表这三个杯子中分别含有[i][j][k]的需要的倒水的次数
代码:
#include<bits/stdc++.h> using namespace std; int f[110][110][110]; int k[4]; struct node{ int w[3]; }; int main(){ while (cin>>k[0]>>k[1]>>k[2],k[0]&&k[1]&&k[2]){ memset(f,-1,sizeof f); queue<node>q; f[k[0]][0][0]=0; q.push({k[0],0,0}); bool st=false; if(k[0]&1){ cout<<"NO\n"; continue; } while (!q.empty()){ auto t=q.front(); q.pop(); int ans=f[t.w[0]][t.w[1]][t.w[2]]; if(t.w[0]==t.w[1]&&!t.w[2]){ cout<<ans<<endl; st= true; break; } if(t.w[0]==t.w[2]&&!t.w[1]){ cout<<ans<<endl; st= true; break; } if(t.w[2]==t.w[1]&&!t.w[0]){ cout<<ans<<endl; st= true; break; } int p[3]; for (int i = 0; i <3 ; ++i) { for (int j = 0; j <3 ; ++j) { p[0]=t.w[0],p[1]=t.w[1],p[2]=t.w[2]; if(i!=j&&(p[i])&&p[j]!=k[j]){ int h=min(p[i],k[j]-p[j]); p[i]-=h; p[j]+=h; if(f[p[0]][p[1]][p[2]]==-1){ f[p[0]][p[1]][p[2]]= ans+1; q.push({p[0],p[1],p[2]}); } } } } } if(st==false){ puts("NO"); } } }
2.哈密顿绕行世界问题
思路:建图时注意去重,主要是记录路径,用&vector记录路径,记得回溯剪枝,排序边保证按照字典序排列
代码:
#include<bits/stdc++.h> using namespace std; vector<int >q[25]; int cnt=1; int vis[25]; int qd; void dfs(vector<int >&t,int u){ if(t.size()==20){ int p=0; for (int i = 0; i <q[t.back()].size() ; ++i) { if(q[t.back()][i]==qd){ p=1; } } if(p){ t.push_back(qd); cout<<cnt<<": "; cnt++; for (auto x:t) { cout<<" "<<x; } cout<<endl; t.pop_back(); } } for (int i = 0; i <q[u].size() ; ++i) { int d=q[u][i]; if(vis[d]==0){ t.push_back(d); vis[d]=1; dfs(t,d); t.pop_back(); vis[d]=0; } } return; } int main(){ set<int >st[25]; for (int i = 1; i <=20 ; ++i) { int x,y,z; cin>>x>>y>>z; if(st[x].insert(i).second== true){ q[x].push_back(i); st[x].insert(i); } if(st[y].insert(i).second== true){ q[y].push_back(i); st[y].insert(i); } if(st[z].insert(i).second== true){ q[z].push_back(i); st[z].insert(i); } } for (int i = 1; i <=20 ; ++i) { sort(q[i].begin(),q[i].end()); } while(1){ cnt=1; cin>>qd; if(qd==0)break; ::memset(vis,0,sizeof vis); vector<vector< int >>ans; vector<int >t; vis[qd]=1; t.push_back(qd); dfs(t,qd); } }
3.A计划
思路:此题最大的特点就是两张图,有传送门,刚开始想用dfs实现,但dfs不一定是最短路,且dfs两个图独立。因此用bfs,特判一下能否可以传送即可
代码:
#include<bits/stdc++.h> using namespace std; void solve(); char mp[3][12][12]; int vis[3][12][12]; int n,m,t; struct node{ int x,y,z,t; }; int dx[4]={-1,1,0,0}; int dy[4]={0,0,-1,1}; int bfs(){ vis[1][1][1]=1; queue<node>q; q.push({1,1,1,0}); while(q.size()){ auto a=q.front(); q.pop(); node b; for (int i = 0; i < 4; ++i) { b.x=a.x+dx[i]; b.y=a.y+dy[i]; b.z=a.z; b.t=a.t+1; if(b.t>t){ return -1; } if(mp[b.z][b.x][b.y]=='#'){ if(b.z==1){ b.z=2; } else b.z=1; } if(b.x<1||b.x>n||b.y<1||b.y>m||mp[b.z][b.x][b.y]=='*'||vis[b.z][b.x][b.y]==1||mp[b.z][b.x][b.y]=='#') continue; else{ vis[b.z][b.x][b.y]=1; q.push(b); if(mp[b.z][b.x][b.y]=='P'){ return b.t; } } } } return -1; } int main(){ int whc; cin>>whc; while(whc--){ solve(); } } void solve(){ ::memset(vis,0,sizeof vis); ::memset(mp,0,sizeof mp); cin>>n>>m>>t; for (int i = 1; i <=2 ; ++i) { for (int j = 1; j <=n ; ++j) { scanf("%s",mp[i][j]+1); } } int time=bfs(); if(time!=-1){ cout<<"YES\n"; } else{ cout<<"NO\n"; } }
4.Eight.八数码问题(easy.version)
思路:我们反向的想,先算从初始状态“12345678x”可以形成哪些状态,因为我们是反向来看的,因此我们从上一个状态到下一个状态若是左,那么我们记录的便是右,相反记录即可,关键一点是这张图的位置我们可以映射为x=i/3,y=i%3,用unordered_map来存每一个状态所需的路径,然后我们return一下,便是答案,查询复杂度是O(1);
不懂的点:G++MLT了,C++AC了
代码:
#include<iostream> #include<vector> #include<queue> #include<string> #include<unordered_map> #include <algorithm> using namespace std; #define int long long #define PII pair<int,int> const int N=1e3+10; string res="12345678x",s(9,0); unordered_map<string ,string >vis; int dx[4]={-1,1,0,0}; int dy[4]={0,0,-1,1}; string dir="durl"; void bfs(){ queue<string >q; q.push(res); while(!q.empty()){ string t=q.front(); q.pop(); int u=t.find('x'); int x=u/3; int y=u%3; string dist=vis[t]; for (int i = 0; i <4 ; ++i) { int a=x+dx[i],b=y+dy[i]; if(0<=a&&a<3&&b>=0&&b<3){ swap(t[u],t[a*3+b]); if(!vis.count(t)){ vis[t]=dist+dir[i]; q.push(t); } swap(t[u],t[a*3+b]); } } } } signed main(){ bfs(); while(cin>>s[0]){ for (int i = 1; i <9 ; ++i) { cin>>s[i]; } if(vis.count(s)){ string ans=vis[s]; reverse(ans.begin(),ans.end()); cout<<ans<<endl; } else{ cout<<"unsolvable\n"; } } }