-
真题--分考场
-
暴力dfs求最优解+剪枝(纯C)
-
#include<stdio.h> #include<string.h> #define N 301 #define min(a,b) a>b?b:a //返回较小的这个数 int gxb[N][N];//关系表 int p[N][N];// 房间状态 int num=N,n; void DFS(int x,int kcs){//x 代表当前安排了多少个人 kcs 代表考场数 if(kcs>=num)return;//剪子 if(x==n+1){num=min(num,kcs);return;}//如果已经安排了n个人,进行判断 int j,k; for(j=1;j<=kcs;j++){//枚举考场 k=0; while(p[j][k]&&!gxb[x][p[j][k]])k++;//找到一个空位 并且与该考场人无关系 if(p[j][k]==0)p[j][k]=x,DFS(x+1,kcs),p[j][k]=0;//满足条件 进行下一考生 } //回溯 p[j][0]=x; DFS(x+1,kcs+1);// 如果所有房间都不满足条件 增加房间 p[j][0]=0;//回溯 } int main(){ int m,i,s1,s2; memset(gxb,0,sizeof(gxb)); memset(p,0,sizeof(p)); scanf("%d\n%d",&n,&m); for(i=1;i<=m;i++){ scanf("%d%d",&s1,&s2); gxb[s1][s2]=gxb[s2][s1]=1;//建关系 } DFS(1,1); printf("%d\n",num); return 0; }
-
详解代码:
memset函数:
-
memset(要操作的数组名,要设置的值,要操作的字节数)
-
对于char类型的数组来说,一个字符占据一个字节。
-
对于int类型的数组来说,一个数字代表四个字节,也就是4*8位二进制位。
-
举例:
int a[4]; memset(a,1,sizeof(a); //注释 先看输出结果:16843009 16843009 16843009 16843009 对于第一个元素a[0]来说:就是把1(00000001)分别赋值给四个字节 a[0]=00000001 00000001 00000001 00000001; 也就是十进制的16843009
深度优先搜索:
-
对于递归的理解:符合条件的输出之后,由最后一个值开始向前走。
#include<stdio.h>
//创建dfs函数
void dfs(int n){
printf("n1=%d\n",n);
//回归
if(n>=10)
return;
//递进
dfs(n+1);
printf("n2=%d\n",n);
}
int main()
{
dfs(0);
return 0;
}
-
用递归求数组的最大值和最小值以及和。
#include<stdio.h>
int arr[100];
int n;
int maxa=0;
int mina=9999;
long long sum=0;
int max(int x,int y)
{
if(x>y)
return x;
else
return y;
}
int min(int x,int y)
{
if(x<y)
return x;
else
return y;
}
//求最大值
void dfs1(int x)
{
if(x>=n)
return;
else
maxa=max(maxa,arr[x]);
dfs1(x+1);
}
//求最小值
void dfs2(int x)
{
if(x>=n)
return;
else
mina=min(mina,arr[x]);
}
//求和
void dfs3(int x)
{
if(x>=n)
return;
else
sum=sum+arr[x];
dfs3(x+1);
}
int main()a
{
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
dfs1(0);//求最大值
printf("%d\n",maxa);
dfs2(0);
printf("%d\n",mina);
dfs3(0);
printf("%d\n",sum);
return 0;
}
要注意的是:c语言没有内置max和min函数,需要额外定义。
-
二维数组的遍历:(运行起来比较直观,遇到尽头会返回)
#include<stdio.h>
int arr[10][10];
bool b[10][10];
//判断上述数组中的元素有没有被遍历过
void dfs(int x,int y)
{
if(x>5 or y>5)
return;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
printf("%d",arr[i][j]);
}
printf("\n");
}
printf("\n");
if(arr[x][y]==0)
{
arr[x][y]=1;
dfs(x+1,y); //竖直方向的递进
dfs(x,y+1);
}
}
int main()
{
dfs(0,0);
return 0;
}
-
求二维数组的最大值:
-
#include<stdio.h> int arr[10][10],maxa=0; int n,m; bool bj[10][10];//是否被标记过 int max(int x,int y) { if(x>y) return x; else return y; } void dfs(int a,int b){ if(a>=n or b>=m) return ; if(bj[a][b]==false){ bj[a][b]=true; maxa=max(maxa,arr[a][b]); dfs(a+1,b); dfs(a,b+1); } } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&arr[i][j]); dfs(0,0); printf("%d",maxa); return 0; }
-
输出4的全排列
#include<stdio.h>
int ans=0;//有多少种排列
int arr[5];
bool b[5];
void dfs(int n)
{
if(n>4)//终止条件
{
ans++;
for(int i=1;i<=4;i++)
printf("%d ",arr[i]);
printf("\n");
}
for(int i=1;i<=4;i++)
{
if(b[i]==false)
{
arr[n]=i;
b[i]=true;
dfs(n+1);
b[i]=false;
}
}
}
int main()
{
dfs(1);
printf("一共有%d种排列",ans);
return 0;
}
-
四阶数独
#include<stdio.h>
int ans;
int arr[25];
bool b1[5][5];//行
bool b2[5][5];//列
bool b3[5][5];//块
int hang[17]={0,1,1,1,1,
2,2,2,2,
3,3,3,3,
4,4,4,4};
int lie[17]={0,1,2,3,4,
1,2,3,4,
1,2,3,4,
1,2,3,4};
int kuai[17]={0,1,1,2,2,
1,1,2,2,
3,3,4,4,
3,3,4,4};
void dfs(int x)
{
//回归
if(x>16)
{
ans++;
for(int i=1;i<=16;i++){
printf("%d ",arr[i]);
if(i%4==0)
printf("\n");
}
printf("\n");
return ;
}
//递进
int h=hang[x],l=lie[x],k=kuai[x];
for(int i=1;i<=4;i++)
{
if(b1[h][i]==false and b2[l][i]==false and b3[k][i]==false){
arr[x]=i;
b1[h][i]==true;b2[l][i]==true; b3[k][i]==true;
dfs(x+1);
b1[h][i]==false;b2[l][i]==false; b3[k][i]==false;
}
}
}
int main()
{
dfs(1);
printf("%d",ans);
return 0;
}