2021年1月27日
早上6点起床打卡
然后睡觉睡到下午 也不晓得几点了
解昨天决残留下来的的问题
N皇后问题
这个题我实在优化不了时间了
于是就打表大法了
搜索代码
#include<stdio.h>
#include<string.h>
#include<math.h>
int n;
int count=0;
int book[11];//用桶的思想来表示是不是用过 就可以省去了一个On的循环
int dfs(int step)
{
if(step==n+1)
{
count++;
return 0;
}
int x=step;
for(int i=1;i<=n;i++)
{
if(step==1)
{
book[step]=i;
dfs(step+1);
}
else
{
int flag=0;
for(int j=1;j<step;j++)
{
if(j+book[j]==step+i||j-book[j]==step-i||i==book[j])flag=1;
//左斜上45°就是一个y=-x+b的函数 所以s+y=b
//右斜上45°就是一个y=x+b的函数 所以y-x=b
}
if(flag==0)
{
book[step]=i;
dfs(step+1);
}
}
}
return 0;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)break;
memset(book,0,sizeof(book));
count=0;
dfs(1);
printf("%d\n",count);
}
return 0;
}
正真的ac代码
#include<stdio.h>
int main()
{
int a[11]={0,1,0,0,2,10,4,40,92,352,724};
int n;
while(~scanf("%d",&n))
{
if(n==0)break;
else printf("%d\n",a[n]);
}
}
E - 棋盘问题
这个问题看似和上面N皇后有点像 其实暗藏玄机
棋盘要是可以选 我也可以不选啊
就是说这一行要是有#就是说可以放下一个棋子 让num+1 我也选择不放 让num不+1 然后让后面几行就有得选了
所以一开始卡了很久
#include<stdio.h>
int n;
int k;
char map[10][10];
int book[10];//列坐标记录 运用桶的思想
int count=0;
int dfs(int step,int num)
{
if(num==k+1)
{
count++;
return 0;
}
if(step==n+1)return 0;
for(int i=1;i<=n;i++)
{
if(book[i]==0&&map[step][i]=='#')
{
book[i]=1;
dfs(step+1,num+1);
book[i]=0;
}
}
dfs(step+1,num);//此行就是放和不放2种 假如可以放 在上面循环放入棋子的都列举出来了
} //但是我们也选择不发尽管他可以放
int main()
{
while(~scanf("%d%d",&n,&k))
{
if(n==k&&k==-1)break;
for(int i=1;i<=n;i++)
{
scanf("%s",&map[i][1]);
}
count=0;
dfs(1,1);
printf("%d\n",count);
}
return 0;
}
K - Prime Path
The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices.
— 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.
1033
1733
3733
3739
3779
8779
8179
The 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.
Input
One line with a positive number: the number of test cases (at most 100). Then for each test case, one line with two numbers separated by a blank. Both numbers are four-digit primes (without leading zeros).
Output
One line for each case, either with a number stating the minimal cost or containing the word Impossible.
Sample Input
3
1033 8179
1373 8017
1033 1033
Sample Output
6
7
0
上面这个题就我来翻译翻译吧
输入 t
然后有t组数据
每组数组2个
位两个质数
然后第一个质数最少几步可以变成第二个质数
变换规则是 个位 十位 百位 千位都可以变但是只能变一个数字
变换后的数字 继续变 直到变成了 第二个数据
例如
1033//百位变成7 一步
1733//千位变成3 两步
3733//个位变成9 三步
3739//十位变成7 四步
3779//千位变成8 五步
8779//百位变成1 六步
8179//变好了6步
这个题 我慢慢讲
我们要把一个数变为另外一个数
例如1033
那么我们有很多个变法
我们可以改变千位1到9任意选择
也可以改变百位,十位,个位0到9任意选择
然后要求是素数 那么我们把这个数全部可以改变的情况都列举出来
然后判断是不是素数 然后存起来
也就是1033的所有可以变为是素数存起来
然后再从这个变出来的数据 再变出来 数据
一直变一直变 知道出现 我们的第二个数据k出现了就 停止
数一数变了几遍就ok了
那么很明显就是bfs
要用质数 所以我先预处理一个素数表 便于判断
int book[10000];//素数表
for(int i=2;i<10000;i++)
{
if(book[i]==0)
{
for(int j=i*2;j<10000;j+=i)
{
book[j]=1;
}
}
}
伪代码
{
while(只要可以变出来数据来)
{
列举出来所有可以变得数据 判断是不是素数
然后判断 是不是k 是k就结束
}
}
ac代码
#include<stdio.h>
#include<string.h>
int ans[10000000][3];
int book[10000];//素数表
int bo[10000];
int main()
{
int t;
for(int i=2;i<10000;i++)
{
if(book[i]==0)
{
for(int j=i*2;j<10000;j+=i)
{
book[j]=1;
}
}
}
scanf("%d",&t);
while(t--)
{
memset(bo,0,sizeof(bo));
int tail=0;
int head=0;
int n;
int k;
scanf("%d%d",&n,&k);
ans[tail][0]=n;
ans[tail++][1]=0;
int count=0;
if(book[k]==1||k<=1000||k>=10000)printf("Impossible\n");
else
while(head<=tail)
{
bo[ans[head][0]]=1;
int flag=0;
if(ans[head][0]==k)break;
for(int i=1;i<=9;i++)
{
int temp=ans[head][0];
int a=temp%10;
temp=temp/10;
int b=temp%10;
temp=temp/10;
int c=temp%10;
temp=temp/10;
int d=temp%10;
int end=i*1000+c*100+b*10+a;
if(bo[end])continue;
else if(book[end]==0)
{
ans[tail][0]=end;
ans[tail][2]=head;
ans[tail++][1]=ans[head][1]+1;
bo[end]=1;
if(end==k)
{
flag=1;
break;
}
}
}
if(!flag)for(int i=0;i<=9;i++)
{
int temp=ans[head][0];
int a=temp%10;
temp=temp/10;
int b=temp%10;
temp=temp/10;
int c=temp%10;
temp=temp/10;
int d=temp%10;
int end=i*100+a+b*10+d*1000;
if(bo[end])continue;
else if(book[end]==0)
{
ans[tail][0]=end;
ans[tail][2]=head;
ans[tail++][1]=ans[head][1]+1;
bo[end]=1;
if(end==k)
{
flag=1;
break;
}
}
}
if(!flag)for(int i=0;i<=9;i++)
{
int temp=ans[head][0];
int a=temp%10;
temp=temp/10;
int b=temp%10;
temp=temp/10;
int c=temp%10;
temp=temp/10;
int d=temp%10;
int end=i*10+a+c*100+d*1000;
if(bo[end])continue;
else if(book[end]==0)
{
ans[tail][0]=end;
ans[tail][2]=head;
ans[tail++][1]=ans[head][1]+1;
bo[end]=1;
if(end==k)
{
flag=1;
break;
}
}
}
if(!flag)for(int i=0;i<=9;i++)
{
int temp=ans[head][0];
int a=temp%10;
temp=temp/10;
int b=temp%10;
temp=temp/10;
int c=temp%10;
temp=temp/10;
int d=temp%10;
int end=i+d*1000+b*10+c*100;
if(bo[end])continue;
else if(book[end]==0)
{
ans[tail][0]=end;
ans[tail][2]=head;
ans[tail++][1]=ans[head][1]+1;
bo[end]=1;
if(end==k)
{
flag=1;
break;
}
}
}
if(flag==1)break;
head++;
}
if(head<=tail)printf("%d\n",ans[tail-1][1]);
else printf("Impossible\n");
// for(int i=tail-1;i>=0;i=ans[i][2])
// {
// printf("%d---",ans[i][0]);
// if(i==0)break;
// }
// printf("\n");
}
}
bfs运用队列 具体就不讲了 因为我也阐述不清楚 呜呜呜
这里说明一下 ans【i】【0】代表数据
ans【i】【1】代表步数
ans【i】【2】代表由哪个数变出来的下标
最后注释的代码是打印变化的由来 也就是ans【i】【2】的作用了在这里没有用book数组是素数表bo数组是表示变过的数 防止重复的数据再变(盲猜 可能死循环)