目录
1.Shuffle'm Up
2.Pots
3.Open the Lock
1.Shuffle'm Up
样例
Inputcopy | Outputcopy |
---|---|
2 4 AHAH HAHA HHAAAAHH 3 CDE CDE EEDDCC | 1 2 2 -1 |
题意:本题要求将s1和s2合并,再将合并的s分为s1和s2,知道s为我们需要得到的期望s,输出此时的洗牌次数。
思路:这里其实很好搜,只是v数组不好设置,这时可以使用STL大法,map<string,int>来记录这个结果是否出现过。
下面是AC代码:
#include<iostream>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef struct{string x,y;int step;
}node;
int main()
{int t;cin>>t;for(int i=1;i<=t;i++){map<string,int>k;//这里map相当于一个vis数组使用 string a,b,c;int n;cin>>n;cin>>a>>b>>c;queue<node>q;node st;st.x=a;st.y=b;st.step=0;q.push(st);int f=0;while(!q.empty()){node h=q.front();q.pop();string pv;for(int i=0;i<n;i++){pv+=h.y[i];//按照要求合并 pv+=h.x[i];}if(pv==c){f=1;//找到目标次数 cout<<i<<" ";cout<<h.step+1<<"\n";//+1才是真正的洗牌次数 break;}if(k[pv]==0){k[pv]=1;node ed;ed.x="",ed.y="";for(int j=0;j<n;j++){ed.x+=pv[j];//s1要上部分 }for(int j=n;j<2*n;j++){ed.y+=pv[j];//s2要下部分 }ed.step=h.step+1;q.push(ed);}}if(!f)cout<<i<<" "<<-1<<"\n";}return 0;
}
2.Pots
示例
Inputcopy | Outputcopy |
---|---|
3 5 4 | 6 FILL(2) POUR(2,1) DROP(1) POUR(2,1) FILL(2) POUR(2,1) |
题意:这里需要我们进行操作,知道a或者b瓶子其中一个的水达到C升,并且输出需要进行多少次操作,并且输出操作的名称。
思路:因为只有ab两个瓶子,所以全部的操作只有6种,所以可以用6个if来判断是否push(当然可以用更加灵活的方法,只是本人想不出),v数组可以用当前ab瓶子里面的水升分别有多少。
下面是AC代码:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef struct
{int capa,capb,step;string s[201];
}node;
int a,b,k;
int v[250][250];
int main()
{cin>>a>>b>>k;queue <node>q;node st;st.capa=0,st.capb=0,st.step=0;//初始状态 v[0][0]=1; q.push(st);int f=0;while(!q.empty()){node r=q.front();q.pop();if(r.capa==k||r.capb==k)//其中一个达到目标容量 {f=1;cout<<r.step<<"\n";for(int i=1;i<=r.step;i++){//输出记录的操作 cout<<r.s[i]<<"\n";}break;}if(!v[a][r.capb])//a瓶子的水装满 {v[a][r.capb]=1;node ed;for(int i=1;i<=r.step;i++){ed.s[i]=r.s[i];}ed.capa=a,ed.capb=r.capb,ed.step=r.step+1,ed.s[ed.step]="FILL(1)";q.push(ed);}if(!v[r.capa][b])//b瓶子的水装满{v[r.capa][b]=1;node ed;for(int i=1;i<=r.step;i++){ed.s[i]=r.s[i];}ed.capa=r.capa,ed.capb=b,ed.step=r.step+1,ed.s[ed.step]="FILL(2)";q.push(ed);}if(!v[0][r.capb])//a瓶子的水倒光 {v[0][r.capb]=1;node ed;for(int i=1;i<=r.step;i++){ed.s[i]=r.s[i];}ed.capa=0,ed.capb=r.capb,ed.step=r.step+1,ed.s[ed.step]="DROP(1)";q.push(ed);}if(!v[r.capa][0])//b瓶子的水倒光 {v[r.capa][0]=1;node ed;for(int i=1;i<=r.step;i++){ed.s[i]=r.s[i];}ed.capa=r.capa,ed.capb=0,ed.step=r.step+1,ed.s[ed.step]="DROP(2)";q.push(ed);}if(!v[max(r.capa-(b-r.capb),0)][min(r.capb+r.capa,b)])//a倒b {v[max(r.capa-(b-r.capb),0)][min(r.capb+r.capa,b)]=1;node ed;for(int i=1;i<=r.step;i++){ed.s[i]=r.s[i];}ed.capa=max(r.capa-(b-r.capb),0),ed.capb=min(r.capb+r.capa,b),ed.step=r.step+1,ed.s[ed.step]="POUR(1,2)";q.push(ed);}if(!v[min(r.capa+r.capb,a)][max(r.capb-(a-r.capa),0)])//b倒a {v[min(r.capa+r.capb,a)][max(r.capb-(a-r.capa),0)]=1;node ed;for(int i=1;i<=r.step;i++){ed.s[i]=r.s[i];}ed.capa=min(r.capa+r.capb,a),ed.capb=max(r.capb-(a-r.capa),0),ed.step=r.step+1,ed.s[ed.step]="POUR(2,1)";q.push(ed);}}if(!f){cout<<"impossible\n";}return 0;
}
3.Open the Lock
样本
Inputcopy | Outputcopy |
---|---|
2 1234 21441111 9999 | 2 4 |
题意:给出两个数字串,将第一个数字串变为第二个数字串需要多少步骤。
思路:思路很简单,就是,每单个数字+1,-1或者与相邻的数字交换位置后的数字串分别入队,只是v数组用map来代替。
下面是AC代码:
#include<map>
#include<queue>
#include<iostream>
#include<string>
using namespace std;
struct node{string s;int step;
};
void solve()
{map<string,int>x;string a,b;cin>>a>>b;node st;st.s=a;st.step=0;queue<node>q;x[a]=1;q.push(st);while(!q.empty()){node k=q.front();q.pop();if(k.s==b){cout<<k.step<<"\n";return ;}for(int i=0;i<4;i++){//单个数字+1 string ts=k.s;if(ts[i]=='9') ts[i]='1';//特殊判断 else ts[i]+=1;if(x[ts]!=1){x[ts]=1;q.push({ts,k.step+1});}}for(int i=0;i<4;i++){//单个数字-1 string ts=k.s;if(ts[i]=='1') ts[i]='9';//特殊判断 else ts[i]-=1;if(x[ts]!=1){x[ts]=1;q.push({ts,k.step+1});}}for(int i=0;i<3;i++){//相邻数字交换 string ts=k.s;swap(ts[i],ts[i+1]);if(x[ts]!=1){x[ts]=1;q.push({ts,k.step+1});}}}
}
int main()
{int t;cin>>t;while(t--){solve();}return 0;
}