Vjudge
A - Catch That Cow
John和奶牛分别在数轴的n和k上,john去找奶牛且奶牛不会动
john有三种移动的方式
1.向前一格
2.向后一格
3.从点x移动到点2*x
求john到奶牛的位置最少需要几步
对于n>k的情况,John只能一步步往后退去找牛,所以步数为n-k
对于n==k的情况,John不用动,这种情况可以和第一种情况合并
对于n<k的情况,通过bfs去搜索最少需要几步
#include<iostream>
#include<queue>
using namespace std;
const int N=1e5+5;
int n,k;
int vis[N]; //标记是否走过该点
int step[N]; //记录步数
bool check(int x){
//判断这个点是否在范围内
if(x>=0 && x<=1e5 )
return true;
return false;
}
int bfs(){
queue <int> q;
int start,next;
step[n]=0;//在n点的时候步数为0
q.push(n);
vis[n]=1;//标记n点走过
while(!q.empty()){
start = q.front();
if(start==k){
// 到达牛的位置 退出
return step[start];
}
q.pop();//记得取出后删除
for(int i=0;i<3;i++){
//三种走法
if(i==0){
//第一种走法,向前一格
next=start+1;
}
if(i==1){
//第二种走法,向后一格
next=start-1;
}
if(i==2){
//第三种走法,从x移到2*x
next=start*2;
}
if(check(next) && vis[next]==0){
//判断在范围内且没有走过
q.push(next);
step[next]=step[start]+1; //步骤+1
vis[next]=1;//标记走过
}
}
}
return -1;
}
int main(){
cin >> n >> k;
if(n>=k){
//这种情况下只能一步步后退
cout <<n-k << endl;
}
else{
cout<<bfs()<<endl;
}
return 0;
}
B - Find The Multiple
给一个n,要求求出一个由0和1构成的数字,使得n能被这个数整除
如果给定n有多个解,其中任何一个都是可以接受的。
从1 开始,在后面依次添加0或者1,即x -> x*10
或x -> x*10+1
当找到一个数能够整除n时,就结束搜索
要注意的是,这题要用ll
#include<iostream>
#include<queue>
typedef long long ll;
using namespace std;
int n;
void bfs(int n){
queue<ll>q;//注意要用ll
q.push(1);
while(!q.empty()){
ll x=q.front();
q.pop();
if(x%n==0){
//找到一个数能够整除n
cout << x << endl;//输出这个数
return;
}
q.push(x*10);//添加0
q.push(x*10+1);//添加1
}
}
int main(){
while(cin >> n && n){
bfs(n);
}
return 0;
}
C - Prime Path
给你t组数据
每组数据给你两个四位数,每次操作只能修改一位数字
要求每次修改后的四位数都是质数
问最少花费(也就是操作次数)几次可以将第一个四位数修改成为第二个四位数
如何修改数字呢?每次将数拆成个十百千四位
改变其中一个数字,在将这四个数字组成四位数
通过判断这个数是不是四位数,并且是不是素数来剪枝
如何判断其是否为素数?埃氏筛
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
const int N=1e4+5;
int n,m;
int vis[N];
int prime[N];//素数表
struct node{
int x;//四位数的值
int cnt;//当前四位数所用的花费
};
void isprime(){
memset(prime,0,sizeof(prime)); // 初始化每一个都是素数
prime[0]=1;//不是素数
prime[1]=1;//不是素数
for(int i=2;i<N;i++){
// 埃氏筛法判断素数
if(!prime[i]){
for(int j=2*i;j<N;j=j+i){
prime[j]=1; //不是素数
}
}
}
}
int check(int x){
//判断是否是四位数并且是素数
if(!prime[x] && x>=1000 && x<=9999){
return 1;
}
else
return 0;
}
void bfs()
{
node st,next;
queue<node>q;
st.x=n;
st.cnt=0;//初始花费为0
vis[st.x]=1;//标记这个数字已经出现
q.push(st);
int a[4];//用来存四位数
while(!q.empty()){
st=q.front();
q.pop();
a[0]=st.x%10;//个位
a[1]=st.x/10%10;//十位
a[2]=st.x/100%10;//百位
a[3]=st.x/1000%10; //千位
for(int i=0;i<4;i++){
//对每一个数字进行改变
int temp=a[i];//标记用于回溯
for(int j=0;j<=9;j++){
//数字可以是0~9
if(a[i]!=j){
a[i]=j;
next.x=a[3]*1000+a[2]*100+a[1]*10+a[0]; // 新的数字
if(next.x==m){
//与m相等,输出答案结束循环
cout << st.cnt+1 << endl;//输出花费,也就是最少操作数
return ;
}
if(check(next.x) && !vis[next.x]){
//判断合法
next.cnt=st.cnt+1;//花费增加
vis[next.x]=1;//标记已经出现
q.push(next);
}
}
}
a[i]=temp; // 回溯
}
}
cout << "Impossible" << endl;//无法修改成为目标四位数
return;
}
int main()
{
int t;
cin>>t;
isprime();//埃氏筛打表
while(t--){
memset(vis,0,sizeof(vis));//初始化
cin>>n>>m;
if(n==m){
//输入的时候两个数就是相等的
cout << 0 << endl;
}
else
bfs();
}
return 0;
}
D - Pots
有两杯水,容量分别为a,b
你可以进行三种操作
1.FILL(i) 装满水
2.DROP(i) 水全部倒掉
3.POUR(i,j) i中的水倒入j
通过最少的操作次数,使得一个罐子里恰好有c升水
同时要输出操作方法
根据题意,可以知道一共有六种操作:
FILL(1) FILL(2) DROP(1) DROP(2) POUR(1,2) POUR(2,1)
要注意的是要在结构体中开一个数组用来记录操作
#include<iostream>
#include<queue>
using namespace std;
const int N=105;
int a,b,c;
bool vis[N][N];
string path[] = {
"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};//六种操作
struct node {
int a, b;//两个水杯中的水的多少
int path[N];//存储路径
int step;//操作步数
};
void pr(int step,int p[]){
//输出
cout << step << endl;//输出操作数
for(int i=0; i<step; i++)
cout << path[p[i]] << endl;//输出每一步的操作
}
void bfs(){
queue<node> q;
node st;
st.a=0;//a水杯初始没有水
st.b=0;//b水杯初始没有水
st.step=0;//输出操作数为0
q.push(st);
vis[st.a][st.b] = <