【三月】第一次课堂练习
P1605
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> using namespace std; int barrier[10][10]; int walkx[5] = {0,0,0,1,-1}; //x方向可以走的选择 int walky[5] = {0,-1,1,0,0}; //y方向可以走的选择 int n,m,t,sx,sy,fx,fy; //n行,m列,t障碍数,sx,sy起点坐标,fx,fy终点坐标 int result = 0; int flag[10][10]; void dfs(int x, int y){ if(x == fx && y == fy){ result++; return; //返回 } else{ for(int i = 1; i <= 4; ++i){ //上下左右四个方向可以走 if(flag[x+walkx[i]][y+walky[i]] == 0 && barrier[x+walkx[i]][y+walky[i]] == 1){ //是否已走过 && 是否有障碍 flag[x][y] = 1; //原先的标记为已走过 dfs(x+walkx[i],y+walky[i]); flag[x][y] = 0; //回溯 } } } } int main(){ scanf("%d%d%d",&n,&m,&t); scanf("%d%d%d%d",&sx,&sy,&fx,&fy); for(int i = 1; i <= n; ++i){ for(int j = 1; j <= m; ++j){ barrier[i][j] = 1; //初始化为地图都不为障碍,即都可以走 } } int barrierx,barriery; for(int i = 1; i<= t; ++i){ scanf("%d%d",&barrierx,&barriery); barrier[barrierx][barriery] = 0; //更新障碍处 } dfs(sx,sy); //从起点开始深搜 printf("%d\n",result); return 0; }
P1451
#include<stdio.h> int m,n; int ans; int cell[105][105]; int vis[105][105]; int dx[4]={1,-1,0,0}; int dy[4]={0,0,1,-1}; void dfs(int x,int y){ vis[x][y]=1; for(int i=0;i<4;i++){ int next_x = x+dx[i]; int next_y = y+dy[i]; if(cell[next_x][next_y] == 0 || vis[next_x][next_y]==1) continue; else dfs(next_x,next_y); } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%1d",&cell[i][j]);//限制输入数字的位数 } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(vis[i][j]==0 && cell[i][j]!=0 ) { //以(i,j)为起点寻找同属同一细胞的点 dfs(i,j); ans++; } } } printf("%d",ans); }
P1784
#include<cstdio> using namespace std; const int N=10; const int group[9][9]= { 0,0,0,1,1,1,2,2,2, 0,0,0,1,1,1,2,2,2, 0,0,0,1,1,1,2,2,2, 3,3,3,4,4,4,5,5,5, 3,3,3,4,4,4,5,5,5, 3,3,3,4,4,4,5,5,5, 6,6,6,7,7,7,8,8,8, 6,6,6,7,7,7,8,8,8, 6,6,6,7,7,7,8,8,8 };//代表9个3*3的区域 bool row[N][N],col[N][N],gr[N][N]; //row[i][j]:判断第i行是否出现过数字j //col[i][j]:判断第i列是否出现过数字j //gr[i][j]:判断区域i是否出现过数字j int sudoku[N][N];//数独 bool check(int x,int y,int w) { if(row[x][w]||col[y][w]||gr[group[x][y]][w])//若该行 或 该列 或 该3*3区域出现过w return 0;//不能填充w return 1;//可填充 } void dfs(int x,int y) { if(x==9)//如果此时棋盘满足约束,则输出 { for(int i=0;i<9;i++) { for(int j=0;j<9;j++) printf("%d ",sudoku[i][j]); printf("\n"); } return; } int nxtx=x,nxty=y+1;//计算下一个状态 if(nxty==9) ++nxtx,nxty=0; if(sudoku[x][y]!=0)//原来就有数字,直接跳过 dfs(nxtx,nxty); else//原来没有数字,枚举所有可能:填充1-9 { for(int j=1;j<=9;j++) if(check(x,y,j)) { row[x][j]=col[y][j]=gr[group[x][y]][j]=1; sudoku[x][y]=j; dfs(nxtx,nxty);//搜索下一状态 sudoku[x][y]=0;//回溯,复原棋盘 row[x][j]=col[y][j]=gr[group[x][y]][j]=0; } } } int main() { for(int i=0;i<9;i++) for(int j=0;j<9;j++) { int a; scanf("%d",&a); if(a==0) continue; row[i][a]=1;//第i行已有a col[j][a]=1;//第j列已有a gr[group[i][j]][a]=1;//i行j列所在区域 已有a sudoku[i][j]=a;//填充入sudoku } dfs(0,0); return 0; }
P1506
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; int a[501][501]; int x,y,ans,dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1}; //dx,dy数组用于遍历上、下、左、右四个位置 //下标为0的地方用0填充即可 void dfs(int n,int m) { if(n<0||m<0||n>x+1||m>y+1||a[n][m]) return ; //边界,如果到建设图外面或者这里有障碍就返回,没法子让洪水灌进来 a[n][m]=1; //染色 for(int i=1;i<=4;i++) dfs(n+dx[i],m+dy[i]); } int main() { scanf("%d%d",&x,&y); for(int i=1;i<=x;i++) { char ch[501]; scanf("%s",ch); for(int j=1;j<=y;j++) { if(ch[j-1]=='0') a[i][j]=0; else a[i][j]=1; //字符 -> 数字 } } dfs(0,0); //染色,可以形象的理解为让洪水全部灌进来 for(int i=1;i<=x;i++) for(int j=1;j<=y;j++) if(!a[i][j]) //如果这个点没有被水淹 ++ans; printf("%d",ans); return 0; }
P2392
#include<bits/stdc++.h> using namespace std; int Left,Right,minn,ans; int s[5]; int a[21][5]; void search(int x,int y){ if(x>s[y]){ minn=min(minn,max(Left,Right)); return; } Left+=a[x][y]; search(x+1,y); Left-=a[x][y]; Right+=a[x][y]; search(x+1,y); Right-=a[x][y]; } int main(){ scanf("%d%d%d%d",&s[1],&s[2],&s[3],&s[4]); for(int i=1;i<=4;i++){ Left=Right=0; minn=19260817; for(int j=1;j<=s[i];j++) scanf("%d",&a[j][i]); search(1,i); ans+=minn; } printf("%d",ans); return 0; }