搜索复习-基础水题(一共12道)
由于是跟着黄学长刷题,此篇博文里所有JudgeOnline都是http://218.5.5.242:9018/JudgeOnline/
tyvj1080 N皇后
描述
列号
1 2 3 4 5 6
-------------------------
1 | | O | | | | |
-------------------------
2 | | | | O | | |
-------------------------
3 | | | | | | O |
-------------------------
4 | O | | | | | |
-------------------------
5 | | | O | | | |
-------------------------
6 | | | | | O | |
-------------------------
上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。
特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出(或是找到一个关于它的公式),这是作弊。如果你坚持作弊,那么你登陆tyvj的帐号将被无警告删除
输入格式
输出格式
测试样例1
输入
6
输出
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=15;
int n,tot,ans[maxn];
bool l[maxn],jia[maxn*2],jian[maxn*2];
void p() {
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
printf("\n");
}
void s(int pos) {
if(pos==n+1) {
if((++tot)<=3) p();
return ;
}
for(int i=1;i<=n;++i) {
if(l[i]||jia[pos+i]||jian[pos-i+n]) continue;
l[i]=jia[pos+i]=jian[pos-i+n]=1;
ans[pos]=i;s(pos+1);
l[i]=jia[pos+i]=jian[pos-i+n]=0;
}
}
int main() {
cin>>n;
s(1);
cout<<tot;
return 0;
}
codevs2080 特殊的质数肋骨
农民约翰的母牛总是产生最好的肋骨。 你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们。 农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还剩下的肋骨上的数字都组成一个质数,举例来说: 7 3 3 1 全部肋骨上的数字 7331是质数;三根肋骨 733是质数;二根肋骨 73 是质数;当然,最后一根肋骨 7 也是质数。 7331 被叫做长度 4 的特殊质数。 写一个程序对给定的肋骨的数目 N(1<=N<=8),求出所有的特殊质数。 数字1不被看作一个质数。
单独的一行包含N。
按顺序输出长度为 N 的特殊质数,每行一个。
4
2333 2339 2393 2399 2939 3119 3137 3733 3739 3793 3797 5939 7193 7331 7333 7393
再来一发
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=10;
int n,ans[maxn];
bool ok(int x) {
if(x==1) return 0;
int y=sqrt(x);
for(int i=2;i<=y;++i) if(x%i==0) return 0;
return 1;
}
void s(int pos,long long x) {
if(!ok(x)) return;
if(pos==n+1) {
printf("%lld\n",x);
return;
}
for(int i=1;i<=9;++i) {
ans[pos]=i;s(pos+1,x*10+i);
}
}
int main() {
cin>>n;
s(1,0);
return 0;
}
RQNOJ67 选数
已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29)。
键盘输入,格式为:
n , k (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)
屏幕输出,格式为:
一个整数(满足条件的种数)。
4 3
3 7 12 19
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=20+5;
int n,k,a[maxn],tot;
bool ok(int x) {
if(x<=1) return 0;
int y=sqrt(x);
for(int i=2;i<=y;++i) if(x%i==0) return 0;
return 1;
}
void s(int pos,int f,int x) {
if(f==k) {
if(ok(x)) tot++;
return;
}
if(pos>n) return;
s(pos+1,f,x);
s(pos+1,f+1,x+a[pos]);
}
int main() {
cin>>n>>k;
for(int i=1;i<=n;++i) cin>>a[i];
s(1,0,0);
cout<<tot;
return 0;
}
codevs1116 四色问题
题目描述
4色问题:对平面或球面的任何一幅地图,只需要使用4种颜色就可以给地图上的每个国家填色,使得任意2个有一段公共边界的国家所填的颜色是不同的。
输入
用邻接矩阵表示地图。读入格式如下:
N(有N个国家,N不超过20)
N行用空格隔开的0/1串(1表示相邻,0表示不相邻)
输出
最多的填色方案
样例输入
0 0 0 1 0 0 1 0
0 0 0 0 0 1 0 1
0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
1 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0
样例输出
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=20+5;
int n,cl[maxn],ans;
bool tu[maxn][maxn];
int get_f(int pos) {
int x=15;
for(int i=1;i<pos;++i) if(tu[i][pos])x-=(x&(1<<(cl[i]-1)));
return x;
}
void s(int pos) {
if(pos>n) {
ans++;
return;
}
int x=get_f(pos);
for(int i=1;i<=4;++i) if(x&(1<<(i-1))) {
cl[pos]=i;
s(pos+1);
}
}
int main() {
cin>>n;
for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cin>>tu[i][j];
s(1);
cout<<ans;
return 0;
}
JudgeOnline1427 寻找国都名
题目描述
给出一个字符矩阵及要寻找的国都名,要求从这个矩阵中找到这个国都名,并输出这个国都名的起始位置及搜索的方向。搜索可沿8个方向进行,见下图:
输入
第一行有一个整数M和N(1<=M,N<=10),表示该字符矩阵的长和宽。接下来就是M*N的字符矩阵。接下来一行是一串字符,代表要寻找的国都名。
输出
样例输入
8 8 okdublin alpgocev rasmusmb oslondon yibdglrc krzurich oaibxmuz tpqglamv dublin
样例输出
1 3 11111
字符串的读入要小心了,或许坑人的什么都有。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=10+5,maxlen=10000+10;
int n,m,len,ans[maxlen],st[3];
char s[maxn][maxn],cc,nme[maxlen];
bool ok;
int f[10][2];
void p() {
ok=1;
printf("%d %d\n",st[0],st[1]);
for(int i=1;i<len;++i) cout<<ans[i];
}
void dfs(int x,int y,int pos) {
if(s[x][y]!=nme[pos]||ok) return;
if(pos==len) p();
int xx,yy;
for(int i=1;i<=8&&!ok;++i) {
xx=x+f[i][0];yy=y+f[i][1];
if(!xx||!yy||xx>n||yy>m) continue;
ans[pos]=i;dfs(xx,yy,pos+1);
}
}
int main() {
cin>>n>>m;
f[1][1]=1;f[2][1]=-1; f[3][0]=1;f[4][0]=-1;
f[5][0]=1;f[5][1]=-1; f[6][0]=-1;f[6][1]=1;
f[7][0]=f[7][1]=1; f[8][0]=f[8][1]=-1;
for(int i=1;i<=n;++i) cin>>s[i]+1;
cin>>nme+1;len=strlen(nme+1);
for(int i=1;i<=n&&!ok;++i) for(int j=1;j<=m&&!ok;++j)
dfs((st[0]=i),(st[1]=j),1);
if(!ok) cout<<"No Answer!";
return 0;
}
JudgeOnline1428: 倒酒
题目描述
分别输入三个杯子容量a,b,c 且第一个为初始杯中的酒量,另外两个为空的。现要求你要精确量出
的e容量的酒。问最少通过几步能精确量出你所要的容量。.例如有三个烧杯容量分别为:80、50、30毫升,现在第一个杯中装满了80
毫升水,其余两个是空的。现要精确的40毫升水,不许用其它工具,请找出最少步骤的方法。 若超过50步,则认为这种计量方法太麻烦
,直接输出“no answer”
输入
80 50 30 40
输出
step1:30 50 0
step2:30 20 30
step3:60 20 0
step4:60 0 20
step5:10
50 20
step6:10 40 30
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=3e4+10;
int a,b,c,e;
int s=1,t=0,f[maxn][5],from[maxn],ans[110];
bool ok=0;
bool ud(int x,int y,int z) {
for(int i=1;i<=t;++i) if(f[i][1]==x&&f[i][2]==y&&f[i][3]==z&&f[i][0]<=f[s][0]+1) return 1;
return 0;
}
void p() {
if(f[t][1]!=e&&f[t][2]!=e&&f[t][3]!=e) return;
ok=1;
for(int i=t;i;i=from[i]) ans[f[i][0]]=i;
for(int i=1;i<=f[t][0];++i)
printf("step%d:%d %d %d\n",i,f[ans[i]][1],f[ans[i]][2],f[ans[i]][3]);
}
void bfs() {
f[++t][0]=0;f[t][1]=a;f[t][2]=f[t][3]=0;p();
int x;
while(s<=t&&!ok) {
if(f[s][0]>=50) break;
//1->2:
x=min(f[s][1],b-f[s][2]);
if(!ok&&x&&!ud(f[s][1]-x,f[s][2]+x,f[s][3])) {
from[++t]=s; f[t][0]=f[s][0]+1;
f[t][1]=f[s][1]-x;f[t][2]=f[s][2]+x;f[t][3]=f[s][3];
p();
}
//1->3:
x=min(f[s][1],c-f[s][3]);
if(!ok&&x&&!ud(f[s][1]-x,f[s][2],f[s][3]+x)) {
from[++t]=s; f[t][0]=f[s][0]+1;
f[t][1]=f[s][1]-x;f[t][2]=f[s][2];f[t][3]=f[s][3]+x;
p();
}
//2->1:
x=min(f[s][2],a-f[s][1]);
if(!ok&&x&&!ud(f[s][1]+x,f[s][2]-x,f[s][3])) {
from[++t]=s; f[t][0]=f[s][0]+1;
f[t][1]=f[s][1]+x;f[t][2]=f[s][2]-x;f[t][3]=f[s][3];
p();
}
//2->3:
x=min(f[s][2],c-f[s][3]);
if(!ok&&x&&!ud(f[s][1],f[s][2]-x,f[s][3]+x)) {
from[++t]=s; f[t][0]=f[s][0]+1;
f[t][1]=f[s][1];f[t][2]=f[s][2]-x;f[t][3]=f[s][3]+x;
p();
}
//3->1:
x=min(f[s][3],a-f[s][1]);
if(!ok&&x&&!ud(f[s][1]+x,f[s][2],f[s][3]-x)) {
from[++t]=s; f[t][0]=f[s][0]+1;
f[t][1]=f[s][1]+x;f[t][2]=f[s][2];f[t][3]=f[s][3]-x;
p();
}
//3->2:
x=min(f[s][3],b-f[s][2]);
if(!ok&&x&&!ud(f[s][1],f[s][2]+x,f[s][3]-x)) {
from[++t]=s; f[t][0]=f[s][0]+1;
f[t][1]=f[s][1];f[t][2]=f[s][2]+x;f[t][3]=f[s][3]-x;
p();
}
s++;
}
}
int main() {
cin>>a>>b>>c>>e;
if(a<e) printf("no answer");
else {
bfs();
if(!ok) printf("no answer");
}
return 0;
}
codevs1961 躲避大龙
你早上起来,慢悠悠地来到学校门口,发现已经是八点整了!(这句话里有一个比较重要的条件)
学校共有N个地点,编号为1~N,其中1号为学校门口(也就是你现在所处的位置),2号为你的教室(也就是你的目的地)。这些地点之间有M条双向道路,对于第i条道路,为了不引起值周队老师的怀疑,你通过它的时间须恰好为Ti秒。这个数可能为负数,意义为时间倒流。
不过,即使没有引起怀疑,值周队也布下了最后一道防线:大龙会在教室处不定期出现。当然,你也了解大龙的习性:当前时间的秒数越小,大龙出现的概率就越低,例如:8:13:06这一时刻的秒数是06,就要比8:12:57这个时刻更加安全。
现在的问题是,在不引起怀疑的前提下,最安全的到达时刻的秒数是多少。如果学校门口到教室没有路(-_-||),请输出60。
注意,你可以选择在途中的任何时候经过教室,而不结束“旅程”,具体见样例。
第一行为两个整数,N和M,意义在上面已经说过了。
第2行~第M+1行,每行代表一条道路。第i+1行代表第i条道路,这一行有3个整数,Ai,Bi,Ti,表示Ai号地点与Bi号地点有一条双向道路,通过它的时间必须为Ti秒。
只有一行,为最安全的到达时刻的秒数。
Input1:
2 1
2 1 54
Input2:
3 3
1 2 26
1 3 17
2 3 -9
Input3:
3 1
1 3 110
Input4:
2 2
1 2 7
2 1 9
Input5:
2 2
1 2 3
1 1 1
Input6:
2 2
1 2 9
1 2 11
Output1:
06
Output2:
00
Output3:
60
Output4:
01
Output5:
00
Output6:
01
样例1的说明:一共只有两个地点(多么福利的数据啊),也只有一条道路,耗时为54秒。最优方案为,经过这个道路9次,耗时486秒,即8分06秒,于8:08:06到达教室。当然,最优方案不唯一。
样例2的说明:走1->3->1->2,用时17+17+26,于8:01:00到达;或走1->2->3->1->2,用时26-9+17+26,于8:01:00到达。
对于20%的数据,N≤2;对于40%的数据,N≤100;对于70%的数据,N≤1000;
对于100%的数据,2≤N≤7000,0≤M≤9000,1≤Ai,Bi≤N,|Ti|≤109。
有一组数据全是大负数。要注意了。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=7e3+10,maxm=9e3+10;
int n,m;
bool g[maxn][70];
int aa,ff;char cc;
int read() {
aa=0;cc=getchar();ff=1;
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
int fir[maxn],nxt[2*maxm],to[2*maxm],e=0,v[2*maxm];
void add(int x,int y,int z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;
}
void s(int pos,int t) {
g[pos][t]=1;
int y,z,tt;
for(y=fir[pos];y;y=nxt[y]) {
z=to[y];tt=(t+v[y]+786666660)%60;
if(!g[z][tt]) s(z,tt);
}
}
int main() {
n=read();m=read();
int x,y,z;
for(int i=1;i<=m;++i) {
x=read();y=read();z=read();
add(x,y,z);
}
s(1,0);
for(int i=0;i<60;++i) if(g[2][i]) {
if(i<10) cout<<"0";
cout<<i;
return 0;
}
cout<<"60";
return 0;
}
codevs1026 逃跑的拉尔夫
年轻的拉尔夫开玩笑地从一个小镇上偷走了一辆车,但他没想到的是那辆车属于警察局,并且车上装有用于发射车子移动路线的装置。
那个装置太旧了,以至于只能发射关于那辆车的移动路线的方向信息。
编写程序,通过使用一张小镇的地图帮助警察局找到那辆车。程序必须能表示出该车最终所有可能的位置。
小镇的地图是矩形的,上面的符号用来标明哪儿可以行车哪儿不行。“.”表示小镇上那块地方是可以行车的,而符号“X”表示此处不能行车。拉尔夫所开小车的初始位置用字符的“*”表示,且汽车能从初始位置通过。
汽车能向四个方向移动:向北(向上),向南(向下),向西(向左),向东(向右)。
拉尔夫所开小车的行动路线是通过一组给定的方向来描述的。在每个给定的方向,拉尔夫驾驶小车通过小镇上一个或更多的可行车地点。
输入文件的第一行包含两个用空格隔开的自然数R和C,1≤R≤50,1≤C≤50,分别表示小镇地图中的行数和列数。
以下的R行中每行都包含一组C个符号(“.”或“X”或“*”)用来描述地图上相应的部位。
接下来的第R+2行包含一个自然数N,1≤N≤1000,表示一组方向的长度。
接下来的N行幅行包含下述单词中的任一个:NORTH(北)、SOUTH(南)、WEST(西)和EAST(东),表示汽车移动的方向,任何两个连续的方向都不相同。
输出文件应包含用R行表示的小镇的地图(象输入文件中一样),字符“*”应该仅用来表示汽车最终可能出现的位置。
4 5
.....
.X...
...*X
X.X..
3
NORTH
WEST
SOUTH
.....
*X*..
*.*.X
X.X..
感觉自己回到了一年前刷搜索基础题的状态,难度差不多,为什么现在没有当时刷的快?
如果今年没去年考的好就搞笑了。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1000+10,maxr=50+5;
int n,R,C,sr[3];
char s[maxr][maxr];
char tn[maxn][10];
bool g[maxr][maxr][maxn];
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
bool ng(int x,int y) {
if(!x||!y||x>R||y>C) return 0;
if(s[x][y]!='.'&&s[x][y]!='*') return 0;
return 1;
}
void dfs(int x,int y,int pos) {
if(g[x][y][pos]||!ng(x,y)) return; g[x][y][pos]=1;
if(tn[pos][0]=='N'&&ng(x-1,y)) dfs(x-1,y,pos);
else if(tn[pos][0]=='S'&&ng(x+1,y)) dfs(x+1,y,pos);
else if(tn[pos][0]=='W'&&ng(x,y-1)) dfs(x,y-1,pos);
else if(tn[pos][0]=='E'&&ng(x,y+1)) dfs(x,y+1,pos);
if(pos==n) {
s[x][y]='*'; return;
}
if(tn[pos+1][0]=='N'&&ng(x-1,y)) dfs(x-1,y,pos+1);
else if(tn[pos+1][0]=='S'&&ng(x+1,y)) dfs(x+1,y,pos+1);
else if(tn[pos+1][0]=='W'&&ng(x,y-1)) dfs(x,y-1,pos+1);
else if(tn[pos+1][0]=='E'&&ng(x,y+1)) dfs(x,y+1,pos+1);
}
int main() {
R=read();C=read();
for(int i=1;i<=R;++i) cin>>s[i]+1;
for(int i=1;i<=R;++i) for(int j=1;j<=C;++j) if(s[i][j]=='*') {
sr[0]=i;sr[1]=j; s[i][j]='.';
break;
}
n=read();
for(int i=1;i<=n;++i) cin>>tn[i];
if(tn[1][0]=='N'&&ng(sr[0]-1,sr[1])) sr[0]--;
else if(tn[1][0]=='S'&&ng(sr[0]+1,sr[1])) sr[0]++;
else if(tn[1][0]=='W'&&ng(sr[0],sr[1]-1)) sr[1]--;
else if(tn[1][0]=='E'&&ng(sr[0],sr[1]+1)) sr[1]++;
dfs(sr[0],sr[1],1);
for(int i=1;i<=R;++i) {
for(int j=1;j<=C;++j) cout<<s[i][j];
cout<<"\n";
}
return 0;
}
codevs2924 数独挑战
“芬兰数学家因卡拉,花费3个月时间设计出了世界上迄今难度最大的数独游戏,而且它只有一个答案。因卡拉说只有思考能力最快、头脑最聪明的人才能破解这个游戏。”这是英国《每日邮报》2012年6月30日的一篇报道。这个号称“世界最难数独”的“超级游戏”,却被扬州一位69岁的农民花三天时间解了出来。
看到这个新闻后,我激动不已,证明我们OI的实力的机会来了,我们虽然不是思考能力最快、头脑最聪明的人,但是我们可以保证在1s之内解题。
好了废话不多说了……
数独是一种填数字游戏,英文名叫Sudoku,起源于瑞士,上世纪70年代由美国一家数学逻辑游戏杂志首先发表,名为Number Place,后在日本流行,1984年将Sudoku命名为数独,即“独立的数字”的省略,解释为每个方格都填上一个个位数。2004年,曾任中国香港高等法院法官的高乐德(Wayne Gould)把这款游戏带到英国,成为英国流行的数学智力拼图游戏。
玩家需要根据9×9盘面上的已知数字,推理出所有剩余位置(数据表示为数字0)的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。
现在给你一个数独,请你解答出来。每个数独保证有解且只有一个。
9行9列。
每个数字用空格隔开。0代表要填的数
行末没有空格,末尾没有回车。
输出答案。
排成9行9列。
行末没有空格,结尾可以有回车。
2 0 0 0 1 0 8 9 0
0 0 7 0 0 0 0 0 0
0 0 0 9 0 0 0 0 7
0 6 0 0 0 1 3 0 0
0 9 0 7 3 4 0 8 0
0 0 3 6 0 0 0 5 0
6 0 0 0 0 2 0 0 0
0 0 0 0 0 0 1 0 0
0 5 9 0 8 0 0 0 3
2 4 5 3 1 7 8 9 6
9 1 7 2 6 8 5 3 4
3 8 6 9 4 5 2 1 7
4 6 2 8 5 1 3 7 9
5 9 1 7 3 4 6 8 2
8 7 3 6 2 9 4 5 1
6 3 8 1 7 2 9 4 5
7 2 4 5 9 3 1 6 8
1 5 9 4 8 6 7 2 3
保证有解,每个数独都由<a href="http://oubk.com/">http://oubk.com</a>数独网提供。
其中数据hard1.in为芬兰数学家提供。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=12;
int ans[maxn][maxn];
bool h[maxn][maxn],le[maxn][maxn],ge[maxn][maxn],ok=0;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int get_ge(int x,int y) {
x=(x-1)/3+1;y=(y-1)/3+1;
return (x-1)*3+y;
}
bool kz(int x,int y,int num) {
if(!num) return 0;
int gg=get_ge(x,y);
if(h[x][num]) return 0;
if(le[y][num]) return 0;
if(ge[gg][num]) return 0;
h[x][num]=le[y][num]=ge[gg][num]=1;
return 1;
}
void p() {
ok=1;
for(int i=1;i<=9;++i) {
printf("%d",ans[i][1]);
for(int j=2;j<=9;++j) printf(" %d",ans[i][j]);
printf("\n");
}
}
void s(int x,int y) {
if(x>9) p();
if(ok) return;
int xx,yy;
xx=x;yy=y+1;xx+=yy/10;yy=(yy-1)%9+1;
if(ans[x][y]) s(xx,yy);
else {
for(int i=1;i<=9&&!ok;++i) if(kz(x,y,i)){
ans[x][y]=i; s(xx,yy);
h[x][i]=le[y][i]=ge[get_ge(x,y)][i]=0;
}
ans[x][y]=0;
}
}
int main() {
for(int i=1;i<=9;++i) for(int j=1;j<=9;++j) ans[i][j]=read(),kz(i,j,ans[i][j]);
s(1,1);
return 0;
}
JudgeOnline1433: 操练士兵
题目描述
如图1,由8个方格构成的训练场,间隔为虚线的表示两方格相通,五个士兵编号分别为1……5,初始时,士兵被随机地排列在任意的5个格子中。士兵可以越过虚线进入相邻的没有被其他士兵占据的格子中,每移动一格算一步。编程:给定5个士兵的初始位置,计算出将士兵排列为目标状态时最少的步数。
输入:5个士兵的初始位置与目标位置。
输出:最优步数,若无解输出-1。样例读入:4567841638对应的输出为:2
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
int S,T,f[12][12]={{0},{2,5,2},{3,1,3,6},{2,2,7},{1,5},{3,1,4,6},{3,2,5,7},{3,3,6,8},{1,7}},ans[maxn],mi[maxn];
bool g[maxn],ok;
bool kz(int x) {
for(int i=1;i<5;++i) for(int j=i+1;j<=5;++j) if(x/mi[i-1]%10==x/mi[j-1]%10) return 0;
return 1;
}
int zz[maxn];
void bfs() {
int s=1,t=0,x,y,z;
memset(ans,0x3f3f3f3f,sizeof(ans));
if(!kz(S)) return;
zz[++t]=S;ans[S]=0;g[S]=1;
while(s<=t&&!ok) {
x=zz[s++];
for(int i=1;i<=5&&!ok;++i) {
y=x/mi[i-1]%10;
for(int j=1;j<=f[y][0]&&!ok;++j) {
z=x+(f[y][j]-y)*mi[i-1];
if(!kz(z)||g[z]) continue;
g[z]=1;zz[++t]=z;
ans[z]=ans[x]+1;
if(z==T) ok=1;
}
}
}
}
int main() {
cin>>S>>T;
mi[0]=1;
for(int i=1;i<=6;++i) mi[i]=mi[i-1]*10;
bfs();
if(ans[T]!=0x3f3f3f3f) cout<<ans[T];
else cout<<"-1";
return 0;
}
codevs1229 数字游戏
- 第一行包含两个整数 N和M(0<N<9,0<M<2000),分别代表纸片的数目和询问的数目。
- 第二行包含N个整数分别代表纸片上写的数字,每个数字可能取0~9。
- 接下来有M行询问,每个询问给出两个整数X和K(0<=x<10^9,0<K<100)。
- 对于每次询问,如果能够用这些纸片拼出符合答案的T,就输出结果T。如果有多个结果,就输出符合要求的最小的T。
- 如果不能拼出,就输出"None"。
4 3
1 2 3 4
5 7
33 6
12 8
1234
None
1324
本来说要搞一道中级水题来打来着,看到黄学长标签里面有一个哈希,就开了这题。
哪里有哈希了嘛。。。明明就是个裸的。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=12,maxtot=4e6;
long long n,m,a[maxn],num[maxtot],tot=0;
bool ok[maxn];
long long aa;char cc;
long long read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
void s(int pos,long long x) {
if(pos>n) {
num[++tot]=x;
return;
}
for(int i=1;i<=n;++i) if(!ok[i]){
ok[i]=1;s(pos+1,x*10+a[i]);ok[i]=0;
}
}
void get_ans(long long x,long long y) {
for(int i=1;i<=tot;++i) if((num[i]+x)%y==0) {
printf("%lld\n",num[i]);return;
}
printf("None\n");
}
int main() {
n=read();m=read();
for(int i=1;i<=n;++i) a[i]=read();
s(1,(long long)0);
sort(num+1,num+tot+1);
tot=unique(num+1,num+tot+1)-(num+1);
long long x,y;
for(int i=1;i<=m;++i) {
x=read();y=read();
get_ans(x,y);
}
return 0;
}
bzoj1611 流星雨
Description
去年偶们湖南遭受N年不遇到冰冻灾害,现在芙蓉哥哥则听说另一个骇人听闻的消息: 一场流星雨即将袭击整个霸中,由于流星体积过大,它们无法在撞击到地面前燃烧殆尽, 届时将会对它撞到的一切东西造成毁灭性的打击。很自然地,芙蓉哥哥开始担心自己的 安全问题。以霸中至In型男名誉起誓,他一定要在被流星砸到前,到达一个安全的地方 (也就是说,一块不会被任何流星砸到的土地)。如果将霸中放入一个直角坐标系中, 芙蓉哥哥现在的位置是原点,并且,芙蓉哥哥不能踏上一块被流星砸过的土地。根据预 报,一共有M颗流星(1 <= M <= 50,000)会坠落在霸中上,其中第i颗流星会在时刻 T_i (0 <= T_i <= 1,000)砸在坐标为(X_i, Y_i) (0 <= X_i <= 300;0 <= Y_i <= 300) 的格子里。流星的力量会将它所在的格子,以及周围4个相邻的格子都化为焦土,当然 芙蓉哥哥也无法再在这些格子上行走。芙蓉哥哥在时刻0开始行动,它只能在第一象限中, 平行于坐标轴行动,每1个时刻中,她能移动到相邻的(一般是4个)格子中的任意一个, 当然目标格子要没有被烧焦才行。如果一个格子在时刻t被流星撞击或烧焦,那么芙蓉哥哥 只能在t之前的时刻在这个格子里出现。请你计算一下,芙蓉哥哥最少需要多少时间才能到 达一个安全的格子。
Input
* 第1行: 1个正整数:M * 第2..M+1行: 第i+1行为3个用空格隔开的整数:X_i,Y_i,以及T_i
Output
输出1个整数,即芙蓉哥哥逃生所花的最少时间。如果芙蓉哥哥无论如何都无法在流星雨中存活下来,输出-1
Sample Input
0 0 2
2 1 2
1 1 2
0 3 5
输入说明:
一共有4颗流星将坠落在霸中,它们落地点的坐标分别是(0, 0),(2, 1),(1, 1)
以及(0, 3),时刻分别为2,2,2,5。
Sample Output
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=300+10,INF=0x3f3f3f3f;
int n,T[maxn][maxn],rf[5][3]={{0},{1,0},{-1,0},{0,1},{0,-1}},ans=INF;
long long aa;char cc;
long long read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int dis[maxn][maxn],zz[maxn*maxn];//<
void bfs() {
int s=1,t=0,x,y,xx,yy;
zz[++t]=0;dis[0][0]=0;
while(s<=t&&ans==INF) {
x=zz[s]/10000;y=zz[s]%10000;s++;
for(int i=1;i<=4&&ans==INF;++i) {
xx=x+rf[i][0];yy=y+rf[i][1];
if(xx<0||yy<0||dis[xx][yy]||!(xx+yy)) continue;
if(dis[x][y]+1<T[xx][yy]) {
dis[xx][yy]=dis[x][y]+1;
if(T[xx][yy]==INF) ans=dis[xx][yy];
zz[++t]=xx*10000+yy;
}
else dis[xx][yy]=INF;
}
}
}
int main() {
n=read();memset(T,0x3f3f3f3f,sizeof(T));
int x,y,z,xx,yy;
for(int i=1;i<=n;++i) {
x=read();y=read();z=read();
T[x][y]=min(T[x][y],z);
for(int j=1;j<=4;++j) {
xx=x+rf[j][0];yy=y+rf[j][1];
if(xx<0||yy<0) continue;
T[xx][yy]=min(T[xx][yy],z);
}
}
bfs();
if(ans!=INF)cout<<ans;
else cout<<"-1";
return 0;
}


浙公网安备 33010602011771号