简单搜索 (附素数优化模板F+) (因为是后来补的博客,题意思路直接粘了网上的)
https://vjudge.net/contest/210085#overview
A
Input
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
Sample Input
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1
Sample Output
2 1
简单dfs,不多解释
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<algorithm> #include<map> #define maxn 200005 using namespace std; int n,k; char mp[10][10]; bool vis[10]; int flag=0; void dfs(int res,int ans) { if(ans==k) { flag++; return ; } if(res>n)return ; for(int j=1;j<=n;j++) { if(mp[res][j]=='#'&&!vis[j]) { vis[j]=true; dfs(res+1,ans+1); vis[j]=false; } } dfs(res+1,ans); } int main() { while(scanf("%d%d",&n,&k)!=EOF){ if(n==-1)break; getchar(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) { scanf("%c",&mp[i][j]); } getchar(); } memset(vis,false,sizeof(vis)); flag=0; dfs(1,0); printf("%d\n",flag); } return 0; }
B --------------简单题+复杂的数据处理+简单dfs 就直接略了(二维改三维真的头疼)
C
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
Input
Output
Sample Input
5 17
Sample Output
4
Hint
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<algorithm> #include<map> #define maxn 200005 using namespace std; int vis[100005]={0}; int o,p; struct node{ int x,step; //x表示值 step表示步数 }s1,s2; //s1用来存第一次变换,s2用来第二次变换 queue<node>que; void solve(int x,int step) { s2.x=x; vis[x]=1;//标记数值x已经走过了 s2.step=step+1; que.push(s2); } int bfs(int a,int b) { int zz; s1.x=a; s1.step=0; que.push(s1); while(!que.empty()) { s1=que.front(); que.pop(); if(s1.x==b)return s1.step; zz=s1.x-1; if(zz>=0&&zz<=100005&&!vis[zz]) { solve(zz,s1.step); } zz=s1.x+1; if(zz>=0&&zz<=100005&&!vis[zz]) { solve(zz,s1.step); } zz=s1.x*2; if(zz>=0&&zz<=100005&&!vis[zz]) { solve(zz,s1.step); } } return -1; } int main() { while(cin>>o>>p) { int sun=bfs(o,p); cout<<sun<<endl; } return 0; }
E
Input
Output
Sample Input
2 6 19 0
Sample Output
10 100100100100100100 111111111111111111
题意:
给一个数n,让你找出一个只有1,0,组成的十进制数,要求是找到的数可以被n整除。
解题思路:
最高位为1, 接下来每一位不是0就是1,双入口bfs
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<algorithm> #include<map> #define maxn 200005 using namespace std; typedef unsigned long long ll; ll tem,n; void bfs(int n) { queue<ll>que; // while(!que.empty()) // que.pop(); que.push(1); while(!que.empty()) { tem=que.front(); que.pop(); if(tem%n==0){cout<<tem<<endl;break;} que.push(tem*10); que.push(tem*10+1); } } int main() { int n; while(cin>>n) { if(n==0)break; bfs(n); } return 0; }
F
— It is a matter of security to change such things every now and then, to keep the enemy in the dark.
— But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know!
— I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door.
— No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime!
— I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds.
— Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime.
Now, the minister of finance, who had been eavesdropping, intervened.
— No unnecessary expenditure, please! I happen to know that the price of a digit is one pound.
— Hmm, in that case I need a computer program to minimize the cost. You don't know some very cheap software gurus, do you?
— In fact, I do. You see, there is this programming contest going on... Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above.
1033The cost of this solution is 6 pounds. Note that the digit 1 which got pasted over in step 2 can not be reused in the last step – a new 1 must be purchased.
1733
3733
3739
3779
8779
8179
Input
Output
Sample Input
3 1033 8179 1373 8017 1033 1033
Sample Output
6 7 0
题意: 给定两个素数(四位数),求第一个数经过几次转换可以得到第二个素数。
转换方式:是变换数中某一位的数字(第一位不能为零,其它的变换数字是0~~9),变换之后的数也为素数。
思路:bfs。搜索求最短路径,非常easy就想到广度优先搜索。由于广度优先搜索。第一次搜到得到的步数就是最少的步数。另外打素数表提高推断的时候的效率。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<algorithm> #include<map> #define maxn 200005 typedef long long ll; using namespace std; struct node{ int x[4]; int step; }; node st,st1,now; ll ans=0; int a,b,c,d,sum; int vis[maxn]; int m,n,t; bool solve(int n)//素数判定 { for(int i=2;i<=sqrt(n);i++) { if(n%i==0) return false; } return true; } int bfs() { memset(vis,0,sizeof(vis)); queue<node>que; while(!que.empty())que.pop(); st.x[0]=m/1000; st.x[1]=(m/100)%10; st.x[2]=(m/10)%10; st.x[3]=m%10; st.step=0; que.push(st); while(!que.empty()) { st1=que.front(); que.pop(); if(st1.x[0]==a&&st1.x[1]==b&&st1.x[2]==c&&st1.x[3]==d) return st1.step; for(int i=0;i<4;i++) for(int j=0;j<=9;j++) { if(i==0&&j==0)continue; //表示第一位置不能为0 if(st1.x[i]==j)continue; //表示如果和原始数值相等的话就不用变换 now.x[0]=st1.x[0]; now.x[1]=st1.x[1]; now.x[2]=st1.x[2]; now.x[3]=st1.x[3]; now.step=st1.step; now.x[i]=j; sum=now.x[0]*1000+now.x[1]*100+now.x[2]*10+now.x[3]; if(solve(sum)&&!vis[sum]) { vis[sum]=1; now.step++; que.push(now); } } } return -1; } int main() { //prime(); cin>>t; while(t--) { cin>>m>>n; a=n/1000;b=(n/100)%10;c=(n/10)%10;d=n%10; ll zz=bfs(); if(zz==-1) cout<<"Impossible"<<endl; else cout<<zz<<endl; } return 0; } 素数筛法的板子(用于判断素数或者求出大区间内所有素数) // 优化后的筛法就可以避免这种不必要的删去操作 //#define Max 1000000 //bool prime[Max]; //void IsPrime(){ // prime[0]=prime[1]=0;prime[2]=1; // for(int i=3;i<max;i++) // prime[i]=i%2==0?0:1; // int t=(int)sqrt(Max*1.0); // for(int i=3;i<=t;i++) // if(prime[i]) // for(int j=i*i;j<Max;j+=2*i)//优化 // prime[j]=0; //} //这就是素数的二次筛法,博士独创~~~~~ //与前两种筛法不同,此种筛法中prime[i]=2*i+3(即:我们只存储奇数,偶数肯定不是素数的) //#define Max 1000000 //bool prime[Max>>1]; //void IsPrime(){ // memset(prime,true,sizeof(prime)); // int n=Max>>1,m=(int)(sqrt(Max*1.0)/2.0); // for(int i=0;i<=m;i++) // if(prime[i]) // for(int j=2*i*i+6*i+3;j<=n;j+=2*i+3) // isprime[j]=false; //}