}
}
3、北大ACM(1942)
PathsonaGrid
TimeLimit:
1000MS
MemoryLimit:
30000K
Description
Imagineyouareattendingyourmathlessonatschool.Onceagain,youareboredbecauseyourteachertellsthingsthatyoualreadymasteredyearsago(thistimehe'sexplainingthat(a+b)2=a2+2ab+b2).Soyoudecidetowasteyourtimewithdrawingmodernartinstead.
Fortunatelyyouhaveapieceofsquaredpaperandyouchoosearectangleofsizen*monthepaper.Let'scallthisrectangletogetherwiththelinesitcontainsagrid.Startingatthelowerleftcornerofthegrid,youmoveyourpenciltotheupperrightcorner,takingcarethatitstaysonthelinesandmovesonlytotherightorup.Theresultisshownontheleft:
Reallyamasterpiece,isn'tit?
Repeatingtheprocedureonemoretime,youarrivewiththepictureshownontheright.Nowyouwonder:
howmanydifferentworksofartcanyouproduce?
Input
Theinputcontainsseveraltestcases.Eachisspecifiedbytwounsigned32-bitintegersnandm,denotingthesizeoftherectangle.Asyoucanobserve,thenumberoflinesofthecorrespondinggridisonemoreineachdimension.Inputisterminatedbyn=m=0.
Output
Foreachtestcaseoutputonalinethenumberofdifferentartworksthatcanbegeneratedusingtheproceduredescribedabove.Thatis,howmanypathsarethereonagridwhereeachstepofthepathconsistsofmovingoneunittotherightoroneunitup?
Youmaysafelyassumethatthisnumberfitsintoa32-bitunsignedinteger.
SampleInput
54
11
00
SampleOutput
126
2
#include
usingnamespacestd;
longlongf(longlongm,longlongn)
{
if(n==0)return1;
elsereturnf(m-1,n-1)*m/n;
}
intmain()
{
longlongm,n;
while(scanf("%I64d%I64d",&n,&m)&&n+m)
{
printf("%I64d\n",f(m+n,min(m,n)));
}
return0;
}
1、(并查集)若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
规定:
x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。
如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
数据输入:
第一行:
三个整数n,m,p,(n<=5000,m<=5000,p<=5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。
以下m行:
每行两个数Mi,Mj,1<=Mi,Mj<=N,表示Ai和Bi具有亲戚关系。
接下来p行:
每行两个数Pi,Pj,询问Pi和Pj是否具有亲戚关系。
数据输出:
P行,每行一个’Yes’或’No’。
表示第i个询问的答案为“具有”或“不具有”亲戚关系。
样例:
Input:
653
12
15
34
52
13
14
23
56
Output:
Yes
Yes
No
代码:
#include
intfather[10000];
intfind(intx)
{
if(father[x]==x)returnx;
else
returnfather[x]=find(father[x]);
}
intmain()
{
intn,m,p;
scanf("%d%d%d",&n,&m,&p);
for(inti=1;i<=n;i++)father[i]=i;
inta,b;
for(inti=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
a=find(a);
b=find(b);
if(a!
=b)father[a]=b;
}
for(inti=1;i<=p;i++)
{
scanf("%d%d",&a,&b);
a=find(a);
b=find(b);
if(a!
=b)
printf("No\n");
else
printf("Yes\n");
}
return0;
}
假设有两个皇后被放置在(i,j)和(k,l)的位置上,明显,当且仅当|i-k|=|j-l|时,两个皇后才在同一条对角线上。
(1)先从首位开始检查,如果不能放置,接着检查该行第二个位置,依次检查下去,直到在该行找到一个可以放置一个皇后的地方,然后保存当前状态,转到下一行重复上述方法的检索。
(2)如果检查了该行所有的位置均不能放置一个皇后,说明上一行皇后放置的位置无法让所有的皇后找到自己合适的位置,因此就要回溯到上一行,重新检查该皇后位置后面的位置。
intPLACE(intn)/*检查当前列能否放置皇后*/
{
//queen[i]==queen[n]用于保证元素不能再同一列
//abs(queen[i]-queen[n])==abs(n-i)用于约束元素不能再同一行且不能再同一条斜线上
inti;
for(i=0;i{
if(queen[i]==queen[n]||abs(queen[i]-queen[n])==abs(n-i))
{
return0;
}
}
return1;
}
∙1
∙2
∙3
∙4
∙5
∙6
∙7
∙8
∙9
∙10
∙11
∙12
∙13
∙14
∙15
具体的实现代码如下:
#include
#include
#definemax4
//sum用于描述解的可能的个数,每当输出一次复合要求的位置
//sum的数量就会被+1
intqueen[max],sum=0;/*max为棋盘最大坐标*/
voidshow()/*输出所有皇后的坐标*/
{
inti;
printf("(");
//i代表行数,queen[i]代表当前行元素所处的列数,
//注意此处下标是从0开始的
for(i=0;i{
printf("%d",queen[i]+1);
}
printf(")\n");
//每次输出一种解的时候,那么他的解的数量就会增加1
sum++;
}
//此函数用于判断皇后当前皇后是否可以放在此位置
intPLACE(intn)/*检查当前列能否放置皇后*/
{
//queen[i]==queen[n]用于保证元素不能再同一列
//abs(queen[i]-queen[n])==abs(n-i)用于约束元素不能再同一行且不能再同一条斜线上
inti;
for(i=0;i{
if(queen[i]==queen[n]||abs(queen[i]-queen[n])==abs(n-i))
{
return0;
}
}
return1;
}
//核心函数,回溯法的思想
voidNQUEENS(intn)/*回溯尝试皇后位置,n为横坐标*/
{
inti;
for(i=0;i{
//首先将皇后放在第0列的位置,对于第一次来说是肯定成立的
//所以第一次将皇后放在第0行0列的位置
queen[n]=i;/*将皇后摆到当前循环到的位置*/
if(PLACE(n))
{
if(n==max-1)
{
show();/*如果全部摆好,则输出所有皇后的坐标*/
}
else
{
NQUEENS(n+1);/*否则继续摆放下一个皇后*/
}
}
}
}
FF31KAHZD1H8ETZ8WWEZWUUVA
intmain()
{
NQUEENS(0);/*从横坐标为0开始依次尝试*/
printf("\n");
printf("总共的解法有%d种\n",sum);
return0;
}
#include
usingnamespacestd;
intqizi[20];//qizi【i】=j表示第i行第j列下有棋
intans[11];//结果存到表中,不存会超时
intn;
intsum;
booljudge(inthang)
{
for(inti=1;i{
if(qizi[i]==qizi[hang]||abs(hang-i)==abs(qizi[hang]-qizi[i]))//对角线的话斜率的绝对值=1
returnfalse;
}
returntrue;
}
voiddfs(inthang)
{
if(hang==n+1)//比如n=2,然后该第二行下棋了,第二行如果能成功选择的话,那么那么新的行数3就等于n+1=3了,实在不懂举个例子看看
sum++;
else
{
for(intj=1;j<=n;j++)//在该行选第几列
{
qizi[hang]=j;
if(judge(hang))
{
dfs(hang+1);//在本行能下棋的话,就接着下下一行的棋
}
}
}
}
intmain()
{
for(n=1;n<=10;n++)
{
sum=0;
dfs
(1);
ans[n]=sum;
}
intq;
while(scanf("%d",&q)!
=EOF)
{
if(q==0)
break;
printf("%d\n",ans[q]);
}
return0;
}