首页 > 试题广场 >

Acute Stroke (30)

[编程题]Acute Stroke (30)
  • 热度指数:5486 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 640M,其他语言1280M
  • 算法知识视频讲解
One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the results of image analysis in which the core regions are identified in each MRI slice, your job is to calculate the volume of the stroke core.

输入描述:
Each input file contains one test case.  For each case, the first line contains 4 positive integers: M, N, L and T, where M and N are the sizes of each slice (i.e. pixels of a slice are in an M by N matrix, and the maximum resolution is 1286 by 128); L (<=60) is the number of slices of a brain; and T is the integer threshold (i.e. if the volume of a connected core is less than T, then that core must not be counted).
Then L slices are given. Each slice is represented by an M by N matrix of 0's and 1's, where 1 represents a pixel of stroke, and 0 means normal. Since the thickness of a slice is a constant, we only have to count the number of 1's to obtain the volume. However, there might be several separated core regions in a brain, and only those with their volumes no less than T are counted. Two pixels are "connected" and hence belong to the same region if they share a common side, as shown by Figure 1 where all the 6 red pixels are connected to the blue one.

Figure 1


输出描述:
For each case, output in a line the total volume of the stroke core.
示例1

输入

3 4 5 2
1 1 1 1
1 1 1 1
1 1 1 1
0 0 1 1
0 0 1 1
0 0 1 1
1 0 1 1
0 1 0 0
0 0 0 0
1 0 1 1
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 1
1 0 0 0

输出

26
        来自博客
               http://blog.csdn.net/sinat_29278271
        欢迎访问
       PS:题解没写完,因为有些题目真的提不起兴趣写题解,但是我又想写完,真纠结啊
       先简述一下题意,给你一个由0和1组成的三维的数组,计算每个由1填充的连通区域中的1的个数,连通的概念可以很容易从题目中那幅图理解,如果个数大于给定的t就将这一区域中的1的个数累加到最终的ans中,最后输出ans,感觉这道题目最难的根本不是编程,而是生词太多。解决的方法无外乎DFS和BFS两种。解法是对每个含有1的点进行搜索,搜索的时候注意不要越界就好了。然后一点微不足道的小技巧是,将三个方向上的位移用dx,dy,dz三个数组表示,

int dx[6] = {1,-1,0,0,0,0};
int dy[6] = {0,0,1,-1,0,0};
int dz[6] = {0,0,0,0,1,-1};、

       这样在求解连通的方块的时候可以使用一个for循环解决,很久以前我并不知道这种方法,在二维的图中每次都是把同样的代码写四遍,那真是一段黑暗的历史。下面是BFS的代码,使用了STL中的queue,将搜索到的每一个值为1的点入队,下一轮搜索的时候则从队列中再取出一个点进行搜索,简单愉快。

       

# include <cstdio>
# include <queue>
using std::queue;

int map[1286][128][60];
struct loca
{
    int x,y,z;
    loca(int _x,int _y,int _z):x(_x),y(_y),z(_z){}
};

int m,n,l,t;
int dx[6] = {1,-1,0,0,0,0};
int dy[6] = {0,0,1,-1,0,0};
int dz[6] = {0,0,0,0,1,-1};
int ans = 0;
int InRange(int x,int y,int z)
{
    return x<m&&x>=0&&y<n&&y>=0&&z<l&&z>=0;
}
void bfs(int x,int y,int z)
{
    int ret = 0;
	queue<loca> que;
	que.push(loca(x,y,z));
	map[x][y][z] = 0;ret++;
	while (!que.empty())
	{
	    loca tp = que.front();que.pop();
	    x = tp.x;
 	    y = tp.y;
 	    z = tp.z;
	    for (int i=0;i<6;i++)
	    {
		    int nx = x + dx[i];
		    int ny = y + dy[i];
		    int nz = z + dz[i];
	        if (InRange(nx,ny,nz)&&map[nx][ny][nz] == 1)
		        {
	        	map[nx][ny][nz] = 0;ret++;
				que.push(loca(nx,ny,nz));
		        }
		}
	} 
	if (ret>=t)
	    ans += ret;
}
int main()
{
    scanf("%d%d%d%d",&m,&n,&l,&t);
    for (int k=0;k<l;k++)
	    for (int i=0;i<m;i++)
	        for (int j=0;j<n;j++)
	            scanf("%d",&map[i][j][k]);
    for (int k=0;k<l;k++)
	    for (int i=0;i<m;i++)
	        for (int j=0;j<n;j++)
	            if (map[i][j][k]==1)
	                bfs(i,j,k);
    printf("%d\n",ans);
    return 0;
}



编辑于 2015-09-06 11:12:48 回复(6)
更多回答
在PAT平台上用DFS解题,最后两个测试点过不去。(查了下是因为内存溢出),不过牛客平台可以通过。最后还是用BFS解法AC了。
两种写法都贴出来吧。
DFS:
#include <bits/stdc++.h>
using namespace std;
int brain[1300][130][65];
int dx[6] = {1,0,-1,0,0,0},dy[6] = {0,-1,0,1,0,0},dz[6] = {0,0,0,0,1,-1};
int m,n,l,t;
int cnt = 0;
void dfs(int x,int y,int z){
    brain[x][y][z] = 0;
    cnt++;
    for(int i = 0;i < 6;i++){
        int nx = x + dx[i],ny = y + dy[i],nz = z + dz[i];
        if((0 <= nx && nx < m) && (0 <= ny && ny < n) && (0 <= nz && nz < l) && brain[nx][ny][nz]){
            dfs(nx,ny,nz);
        }
    }
}
int main() {
    scanf("%d %d %d %d",&m,&n,&l,&t);
    for(int z = 0;z < l;z++){
        for(int x = 0;x < m;x++){
            for(int y = 0;y < n;y++) scanf("%d",&brain[x][y][z]);
        }
    }
    int sum = 0;
    for(int i = 0;i < m;i++){
        for(int j = 0;j < n;j++){
            for(int k = 0;k < l;k++){
                cnt = 0;
                if(brain[i][j][k]) dfs(i,j,k);
                sum += cnt < t ? 0 : cnt;
            }
        }
    }
    printf("%d\n",sum);
    return 0;
}
BFS:
#include <bits/stdc++.h>
using namespace std;
int brain[1300][130][65];
int dx[6] = {1,-1,0,0,0,0},dy[6] = {0,0,1,-1,0,0},dz[6] = {0,0,0,0,1,-1};
int m,n,l,t;
struct position{
    int x,y,z;
    position(int x,int y,int z):x(x),y(y),z(z){}
};
int bfs(int x,int y,int z){
    int cnt = 0;
    queue<position> q;
    q.push(position(x,y,z));
    brain[x][y][z] = 0;
    while(!q.empty()){
        position pos = q.front();q.pop();
        cnt++;
        for(int i = 0;i < 6;i++){
            int nx = pos.x + dx[i],ny = pos.y + dy[i],nz = pos.z + dz[i];
            if((0 <= nx && nx < m) && (0 <= ny && ny < n) && (0 <= nz && nz < l) && brain[nx][ny][nz]){
                brain[nx][ny][nz] = 0;
                q.push(position(nx,ny,nz));
            }
        }
    }
    return cnt < t ? 0 : cnt;
}
int main() {
    scanf("%d %d %d %d",&m,&n,&l,&t);
    for(int z = 0;z < l;z++){
        for(int x = 0;x < m;x++){
            for(int y = 0;y < n;y++) scanf("%d",&brain[x][y][z]);
        }
    }
    int sum = 0;
    for(int i = 0;i < m;i++){
        for(int j = 0;j < n;j++){
            for(int k = 0;k < l;k++) if(brain[i][j][k]) sum += bfs(i,j,k);
        }
    }
    printf("%d\n",sum);
    return 0;
}



发表于 2020-02-12 16:00:49 回复(0)
#include <iostream>
using namespace std;
int m, n, l, t;
void spread(int ***a, int i, int j, int k, int &vol) {
    vol++;
    a[i][j][k] = 0;
    if (i > 0 && a[i - 1][j][k] == 1) spread(a, i - 1, j, k, vol);
    if (j > 0 && a[i][j - 1][k] == 1) spread(a, i, j - 1, k, vol);
    if (k > 0 && a[i][j][k - 1] == 1) spread(a, i, j, k - 1, vol);
    if (i < l - 1 && a[i + 1][j][k] == 1) spread(a, i + 1, j, k, vol);
    if (j < m - 1 && a[i][j + 1][k] == 1) spread(a, i, j + 1, k, vol);
    if (k < n - 1 && a[i][j][k + 1] == 1) spread(a, i, j, k + 1, vol);
}
int main() {
    ios::sync_with_stdio(false);
    cin >> m >> n >> l >> t;
    int ***a;
    a = new int **[l + 1];
    for (int i = 0; i < l; i++) {
        a[i] = new int *[m + 1];
        for (int j = 0; j < m; j++) {
            a[i][j] = new int[n + 1];
            for (int k = 0; k < n; k++) {
                cin >> a[i][j][k];
            }
        }
    }
    int vol, sum = 0;
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < m; j++) {
            for (int k = 0; k < n; k++) {
                if (a[i][j][k] == 1) {
                    vol = 0;
                    spread(a, i, j, k, vol);
                    if (vol >= t)sum += vol;
                }
            }
        }
    }
    cout << sum << endl;
}
发表于 2021-03-09 16:25:06 回复(0)
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
struct node{
 int x,y,z;
}Node;
int m,n,l,t;
int matrix[1290][130][61];
int inq[1290][130][61]={false};
int X[6]={0,0,0,0,1,-1};
int Y[6]={0,0,1,-1,0,0};
int Z[6]={1,-1,0,0,0,0};
bool judge(int x,int y,int z){
 if(x>=m||x<0||y>=n||y<0||z>=l||z<0) return false;
 if(matrix[x][y][z]==0||inq[x][y][z]==true) return false;
 return true;
}
int BFS(int x,int y,int z){
 int tempt=0;
 queue<node> q;
 Node.x=x;Node.y=y;Node.z=z;
 q.push(Node);
 inq[x][y][z]=true;
 while(!q.empty()){
  node top=q.front();
  q.pop();
  tempt++;
  for(int i=0;i<6;i++){
   int newx=top.x+X[i];
   int newy=top.y+Y[i];
   int newz=top.z+Z[i];
   if(judge(newx,newy,newz)){
    Node.x=newx;Node.y=newy;Node.z=newz;
    q.push(Node);
    inq[newx][newy][newz]=true;
   }
  }
 }
 if(tempt>=t) return tempt;
 else return 0;
}
int main(){
 cin>>m>>n>>l>>t;
 for(int z=0;z<l;z++)
  for(int x=0;x<m;x++)
   for(int y=0;y<n;y++)
    cin>>matrix[x][y][z];
 int ans=0;
 for(int z=0;z<l;z++)
  for(int x=0;x<m;x++)
   for(int y=0;y<n;y++)
    if(matrix[x][y][z]==1&&inq[x][y][z]==false)
     ans+=BFS(x,y,z);
 cout<<ans;
 return 0;
} 

发表于 2019-01-09 18:38:43 回复(0)
/*
https://www.nowcoder.com/pat/5/problem/4317
Acute Stroke (30) 2018-12-21
General mean: give you a Three-Dimensional Array behalf of a cube . Group those little sub-cube
that directly connected into groups. And tell how many little sub-cub in all groups totally have.
Result: Cost me about three hours, and get acpected in first shoot. It is not a hard problem but 
it have many details to be careful. Most of the time i have spend is to debug, Should't be like it!
I devide the code in different funtion so it can make my thought more clearly. The first time I do 
that I make a three-dimensianal array to record the total munber of the group those node belong to,
and use a stack<Dir> to recall after queue<Dir> become empty. But It is unnecessary, so I dont use 
them in the second times, the code become more beautiful !
*/
#include<iostream>
#include<stdio.h>
#include<queue>
const int maxM = 1300;
const int maxN = 130;
const int maxH = 70;
int square[maxH][maxN][maxM];    
bool vis[maxH][maxN][maxM]; 
using namespace std;
int N, M, L, T;
int ans = 0;
struct Dir{   //the three-dimensianal index of a node
    int h, x, y;
};
Dir dir[6] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, { 0, -1, 0 }, { -1, 0, 0 } };    //tag of direction
bool check(Dir a){
    //one of the serious mistakes is that I mixed the N and M in the following line !!!
    bool x = (a.h >= 0 && a.h < L && a.x >= 0 && a.x < N && a.y >= 0 && a.y < M);
    if ( !x ) return false;        //notice that if x==false, square[][][] may out of bounds. 
    bool y = !vis[a.h][a.x][a.y];
    bool z = square[a.h][a.x][a.y];
    return ( y && z);
}
int bfs(int h, int x, int y){  //before bfs, make sure it node haven't vesited
    queue<Dir>que;
    int member = 1;        //total piece of a whole chunk
    que.push({ h,x,y });
    vis[h][x][y] = 1;
    while (!que.empty()){
        int hh = que.front().h, xx = que.front().x, yy = que.front().y;
        que.pop();
        for (int i = 0; i < 6; i++){
            int nh = hh + dir[i].h, nx = xx + dir[i].x, ny = yy + dir[i].y;
            if ( check({ nh, nx, ny }) ){
                vis[nh][nx][ny] = 1;
                member++;
                que.push({ nh, nx, ny });
            }
        }    
    }
    if (member >= T) ans += member;
    return 0;
}
int main(){
    scanf("%d%d%d%d", &N, &M, &L, &T);
    for (int i = 0; i < L; i++){
        for (int j = 0; j < N; j++)
            for (int k = 0; k < M; k++)
                scanf("%d", &square[i][j][k]);
    }
    for (int i = 0; i < L; i++){
        for (int j = 0; j < N; j++)
            for (int k = 0; k < M; k++)
                //if(vis[i][j][k]==0) bfs(i, j, k); it is one of the mistake too.
                if (check({ i, j, k })) bfs(i,j,k);
    }
    cout << ans << endl;
    return 0;
}

发表于 2018-12-21 20:52:22 回复(0)
Physicaloser,
题目一直么怎么看懂,又很急躁,就看了一下各位大牛的答案
发现题目关键还是很简单的,不能太急躁了。
现在对题目关键语句进行翻译:

Two pixels are "connected" and hence belong to the same region 
if they share a common side, as shown by Figure 1 where all the 6 
red pixels are connected to the blue one.
综合思想:
输入 M, N, L and T,
(M,N)的矩阵,L是有几个这样的矩阵。
T是阈值,connected的个数大于这个数就算是肿瘤的个数。  

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

vector<vector<vector<int> > > arr;
vector<vector<vector<int> > > marked;
int M,N,L,T;
int dx[6] = {1,-1,0,0,0,0};
int dy[6] = {0,0,1,-1,0,0};
int dz[6] = {0,0,0,0,1,-1};
int count = 0;
int ans = 0;
void dfs(int i, int j, int k);
int main()
{
    cin >> M >> N >> L >> T;
    arr.resize(L);
    marked.resize(L);
    for(int i=0; i<L; i++)
    {
        arr[i].resize(M);
        marked[i].resize(M);
    }
    for(int i=0; i<L; i++)
    {
        for(int j=0; j<M; j++)
        {
            arr[i][j].resize(N);
            marked[i][j].resize(N);
        }
    }

    for(int i=0; i<L; i++)
    {
        for(int j=0; j<M; j++)
        {
            for(int k=0; k<N; k++){
               int temp;
               cin >> temp;
               arr[i][j][k] = temp;
            }
        }
    }
    for(int i = 0; i<L; i++)
    {
        for(int j=0; j<M; j++)
        {
            for(int k=0; k<N; k++)
            {
                if(arr[i][j][k] == 1 && !marked[i][j][k])
                {
                    count = 0;
                    dfs(i, j, k);
                    if(count >= T)
                        ans += count;
                }
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

void dfs(int i, int j, int k)
{
    int t, x, y, z;

    marked[i][j][k] = 1;
    if(arr[i][j][k] == 0)
        return;
    count ++;
    for(t=0; t<6; t++)
    {
        x = i + dx[t];
        y = j + dy[t];
        z = k + dz[t];
        if (x >= 0 && y >= 0 && z >= 0 &&  x < L  && y < M && z < N && !marked[x][y][z])
            dfs(x, y, z);
    }
    return;
}


发表于 2018-07-25 15:22:06 回复(0)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>

using namespace std;

int G[1286][128][60];

class block
{     public:         int x,y,z;         block(int xx, int yy, int zz):x(xx),y(yy),z(zz){}
};

int M,N,L,T;
int dx[6] = {1,-1,0,0,0,0};
int dy[6] = {0,0,1,-1,0,0};
int dz[6] = {0,0,0,0,1,-1};
int ans = 0;

bool isValid(int x, int y, int z)
{     return x<M && x>=0 && y<N && y>=0 && z<L && z>=0; 
}

void BFS(int x, int y, int z)
{     int result = 0;     queue<block> q;     q.push(block(x,y,z));     G[x][y][z] = 0;     result++;     while(!q.empty())     {         block t = q.front();         q.pop();         x = t.x;         y = t.y;         z = t.z;         for(int i=0;i<6;i++)          {             int xx = x + dx[i];             int yy = y + dy[i];             int zz = z + dz[i];             if(isValid(xx, yy, zz) && G[xx][yy][zz]==1)             {                 G[xx][yy][zz] = 0;                 result++;                 q.push(block(xx,yy,zz));             }         }     }     if(result >= T)         ans += result;
}

int main()
{     cin>>M>>N>>L>>T;     for(int k=0;k<L;k++)         for(int i=0;i<M;i++)              for(int j=0;j<N;j++)                 cin>>G[i][j][k];     for(int k=0;k<L;k++)         for(int i=0;i<M;i++)             for(int j=0;j<N;j++)                 if(G[i][j][k] == 1)                     BFS(i,j,k);     cout<<ans<<endl;     return 0;
}

发表于 2018-02-09 00:12:58 回复(0)
我的DFS竟然过了。。不知道为啥
#include <stdio.h>

int a[60][1286][128];
int marked[60][1286][128];
int dx[6] = {-1, 1, 0, 0, 0, 0};
int dy[6] = {0, 0, 1, -1, 0, 0};
int dz[6] = {0, 0, 0, 0, 1, -1};
int count;

void dfs(int i, int j, int k);

int main(void) {
    int m, n, l, t, i, j, k;
    int volume = 0;
    
    scanf("%d %d %d %d", &m, &n, &l, &t);
    for (i = 0; i < l; i++) {
        for (j = 0; j < m; j++) {
            for (k = 0; k < n; k++) {
                scanf("%d", &a[i][j][k]);
            }
        }
    }
    
    for (i = 0; i < l; i++) {
        for (j = 0; j < m; j++) {
            for (k = 0; k < n; k++) {
                if (a[i][j][k] == 1 && !marked[i][j][k]) {
					count = 0;

                    dfs(i, j, k);
					
					if (count >= t)
						volume += count;
                }
            }
        }
    }
    printf("%d\n", volume);
}

void dfs(int i, int j, int k) {
    int t, x, y, z;

    marked[i][j][k] = 1;
    if (a[i][j][k] == 0 )
        return;
    count++;
    for (t = 0; t < 6; t++) {
        x = i+dx[t];
        y = j+dy[t];
        z = k+dz[t];
        if (x >= 0 && y >= 0 && z >= 0 && !marked[x][y][z])
            dfs(x, y, z);
    }
    return;
}

发表于 2017-08-04 23:51:59 回复(1)
没想过bfs,想到并查集来做的
#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 50;
const int maxn = 1e3 + 500;
const int maxnc = 2e7 + 1000;
int a[66][maxn][N];
int v[maxnc];
int y[66][maxn][N];
//并查集原地秒杀 
int fa[maxnc]; 
void init(int m, int n, int l){
	for(int i = 0; i <= m*n*l; i++){
		fa[i] = i;
	}
}
int find(int x){
	if(x == fa[x]){
		return x;
	}else{
		fa[x] = find(fa[x]);
		return find(fa[x]);
	}
}
void merge(int x, int y){
	int fx = find(x);
	int fy = find(y);
	if(fx != fy){
		fa[fx] = fy;
	}
}
int cal(int i, int j, int k, int m, int n){
	return  (i - 1)*m*n + (j - 1)*n + k;
}
int main(){
	int m, n, l, t;
	cin>>m>>n>>l>>t;
	int cnt = 0;
	init(m, n, l);
	for(int i = 1; i <= l; i++){
		for(int j = 1; j <= m; j++){
			for(int k = 1; k <= n; k++){
				scanf("%d", &a[i][j][k]);
			}
		}
	}
	for(int i = 1; i <= l; i++){
		for(int j = 1; j <= m; j++){
			for(int k = 1; k <= n; k++){
				int x = cal(i, j, k, m, n);
				if(a[i][j][k]){
                   if(a[i-1][j][k])  merge(x, cal(i-1,j,k,m,n));
				   if(a[i][j-1][k])  merge(x, cal(i,j-1,k,m,n));
				   if(a[i][j+1][k])   merge(x, cal(i, j+1,k,m,n));
				   if(a[i][j][k-1])   merge(x, cal(i,j,k-1,m,n));
				   if(a[i][j][k+1])   merge(x, cal(i,j,k+1,m,n));
				}
			}
		}
	}
	for(int i = 1; i <= l; i++){
		for(int j = 1; j <= m; j++){
			for(int k = 1; k <= n; k++){
				int x = cal(i, j, k, m, n);
			    if(a[i][j][k])  v[find(x)]++;
			}
		}
	}	
	int ans = 0;
    for(int i = 0; i <= m*n*l; i++){
    	if(v[i] >= t)  ans = ans + v[i];
	}
	cout<<ans<<endl;
	return 0;
}
发表于 2023-01-28 19:09:58 回复(0)
#include<bits/stdc++.h>
using namespace std;

struct Node {
	int x,y,z;
	Node() {};
	Node(int a,int b,int c):x(a),y(b),z(c) {};
} node;

int m,n,s,t;
int a[1290][130][65];
bool b[1290][130][65];
int X[6]= {0,0,-1,1,0,0};
int Y[6]= {0,0,0,0,-1,1};
int Z[6]= {1,-1,0,0,0,0};

bool Judge(int x,int y,int z) {
	if(x>=m||x<0||y>=n||y<0||z>=s||z<0) return 0;
	if(a[x][y][z]==0||b[x][y][z]) return 0;
	return 1;
}

int BFS(int x,int y,int z) {
	queue<Node> q;
	q.emplace(Node(x,y,z));
	b[x][y][z]=1;
	int total=0;
	while(!q.empty()) {
		Node now=q.front();
		q.pop();
		total++;
		for(int i=0; i<6; i++) {
			int newx=now.x+X[i];
			int newy=now.y+Y[i];
			int newz=now.z+Z[i];
			if(Judge(newx,newy,newz)) {
				q.emplace(Node(newx,newy,newz));
				b[newx][newy][newz]=1;
			}
		}
	}
	if(total>=t) {
		return total;
	} else {
		return 0;
	}
}

int main() {
	scanf("%d %d %d %d",&m,&n,&s,&t);
	for(int k=0; k<s; k++) {
		for(int i=0; i<m; i++) {
			for(int j=0; j<n; j++) {
				scanf("%d",&a[i][j][k]);
			}
		}
	}
	int ans=0;
	for(int k=0; k<s; k++) {
		for(int i=0; i<m; i++) {
			for(int j=0; j<n; j++) {
				if(a[i][j][k]==1&&!b[i][j][k]) {
					ans+=BFS(i,j,k);
				}
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}

发表于 2022-11-22 15:10:57 回复(1)
#include <iostream>
#include<vector>
using namespace std;
bool brain[1286][128][60];
bool mark[1286][128][60]{ false };
int M, N, L, T;

//递归DFS
int DFS(int i, int j, int k) {
	if (i < 0 || i >= M || j < 0 || j >= N || k < 0 || k >= L || mark[i][j][k] || brain[i][j][k] == 0) return 0;
	int _count = 1;
	mark[i][j][k] = true;
	_count += DFS(i + 1, j, k);
	_count += DFS(i - 1, j, k);
	_count += DFS(i, j + 1, k);
	_count += DFS(i, j - 1, k);
	_count += DFS(i, j, k + 1);
	_count += DFS(i, j, k - 1);
	return _count;
}
//迭代DFS
int _DFS(int i, int j, int k) {
	if (mark[i][j][k]) return 0;
	int count = 1;
	vector<vector<int>> stack;
	int offset[][6]{ {1,-1,0,0,0,0},{0,0,1,-1,0,0},{0,0,0,0,1,-1} };
	vector<int> start_point;
	start_point.push_back(i);
	start_point.push_back(j);
	start_point.push_back(k);
	stack.push_back(start_point);
	mark[i][j][k] = true;
	while (stack.size()) {
		vector<int> point = stack.back();
		stack.pop_back();
		for (int i = 0; i < 6; i++) {
			int x = point[0] + offset[0][i], y = point[1] + offset[1][i], z = point[2] + offset[2][i];
			if (brain[x][y][z]&&!mark[x][y][z]) {
				mark[x][y][z] = true;
				vector<int> next_point;
				next_point.push_back(x);
				next_point.push_back(y);
				next_point.push_back(z);
				stack.push_back(next_point);
				count++;
			}
		}
	}
	return count < T ? 0 : count;
}

int main() {
	int count = 0;
	cin >> M >> N >> L >> T;
	for (int k = 0; k < L; k++)for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) cin >> brain[i][j][k];   //递归解法
        //for (int k = 0; k < L; k++) for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) if (brain[i][j][k] == true) {
	//	int v = DFS(i, j, k);
	//	count += v < T ? 0 : v;
	//}
	//迭代解法
        for (int k = 0; k < L; k++) for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) if (brain[i][j][k] == true)count += _DFS(i, j, k);
	cout << count;
}

编辑于 2020-06-04 20:59:48 回复(0)
dfs找到所有联通的点个数,注意判断其点的个数小于阈值的时候不能在递归里面判断,因为后续递归这个值应该返回到前层中去,如果这里判断其小于阈值的时候就令其为0,那后续返回后会使原来的值错误。应该在调用dfs后判断。
//
#include<iostream>
(720)#include<memory.h>
using namespace std;
int matrix[61][1287][129];
int visit[61][1287][129];
int M, N, L, T;
int dx[6] = { 1,-1,0,0,0,0 };
int dy[6] = { 0,0,1,-1,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };
int dfs(int x, int y, int z) {
	int geshu = 0;
	if (visit[z][y][x]||matrix[z][y][x]==0) { return 0; }
	visit[z][y][x] = 1;
	for (int i = 0; i < 6; i++) {
		if (z + dz[i] < L && z + dz[i] >= 0 && y + dy[i] >= 0 && y + dy[i] < M && x + dx[i] >= 0 && x + dx[i] < N) {
			geshu += dfs(x+dx[i], y + dy[i], z + dz[i]);
		}
	}
	return geshu + 1;
}
int main() {
	memset(matrix, 0, sizeof(matrix));
	memset(visit, 0, sizeof(visit));
	//freopen("C:\\Users\\47\\Desktop\\1.txt","r",stdin);
	cin >> M >> N >> L >> T;
	for (int i = 0; i < L; i++) {
		for (int j = 0; j < M; j++) {
			for (int k = 0; k < N; k++) {
				cin >> matrix[i][j][k];
			}
		}
	}
	int num = 0;
	for (int i = 0; i < L; i++) {
		for (int j = 0; j < M; j++) {
			for (int k = 0; k < N; k++) {
				int t = dfs(k, j, i);
				if (t >= T) {
					num += t;
				}
			}
		}
	}
	printf("%d", num);
}

发表于 2020-02-22 20:06:13 回复(0)
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
	 int x,y,z;
}Node;
int n,m,slice,T;
int pix[1290][130][61];//三维01矩阵 
bool in[1290][130][61]={false};//记录位置(x,y,z)是否已经入过队 
int X[6]={0,0,0,0,1,-1};//增量矩阵 
int Y[6]={0,0,1,-1,0,0};
int Z[6]={1,-1,0,0,0,0};
bool judge(int x,int y,int z){
	if(x>=n||x<0||y>=m||y<0||z>=slice||z<0) return false;//判断越界 
	if(pix[x][y][z]==0||in[x][y][z]==true) return false;
	return true;
}
int BFS(int x,int y,int z){
	int tot=0;//计数当前块中的1的个数
	queue<node> Q;//队列
	Node.x=x,Node.y=y,Node.z=z;//结点Node的位置为(x,y,z) 
	Q.push(Node);//结点Node入队 
	in[x][y][z]=true;
	while(!Q.empty()){
		node top=Q.front();//取出队首元素
		Q.pop();//队首元素出队
		tot++;
		for(int i=0;i<6;i++){
			int newX=top.x+X[i];
			int newY=top.y+Y[i];
			int newZ=top.z+Z[i];
			if(judge(newX,newY,newZ)){
				Node.x=newX,Node.y=newY,Node.z=newZ;
				Q.push(Node);
				in[newX][newY][newZ]=true;
			}
		} 
	}
	if(tot>=T) return tot;
	else return 0;
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m>>slice>>T;//矩阵n*m ,共有slice层,T为1个数的下限 
	for(int z=0;z<slice;z++){//先枚举矩阵编号 
		for(int x=0;x<n;x++){
			for(int y=0;y<m;y++){
				cin>>pix[x][y][z];
			}
		}
	}
	int ans=0;//记录核心区中的1的个数总和
	for(int z=0;z<slice;z++){
		for(int x=0;x<n;x++){
			for(int y=0;y<m;y++){
				if(pix[x][y][z]==1&&in[x][y][z]==false){
					ans+=BFS(x,y,z);
				}
			}
		}
	} 
	cout<<ans<<endl;
	return 0;
} 
/*
3 4 5 2   //分为五层,每层三行四列的二维矩阵,合起来就是三维矩阵 
1 1 1 1
1 1 1 1
1 1 1 1 
0 0 1 1
0 0 1 1
0 0 1 1
1 0 1 1
0 1 0 0
0 0 0 0
1 0 1 1
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 1
1 0 0 0*/

发表于 2019-10-30 09:38:21 回复(0)
这题第一眼看完觉得能用并查集搞,然后想了想这题集特别爱dfs,于是用dfs水了一趟,牛客过了,PTA那segmentation fault了两个数据点。想了想应该是爆栈了,加了个手工开栈的黑科技,过了其中一个,另一个还不行,加到50MB还是不行,再高要MLE了。遂改用并查集,发现用vector路径压缩会超时,把vector提到外面就可以了。
正解应该是bfs,一时间没注意到,并查集写得有点麻烦。
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstdlib>

using namespace std;

const int MAX_N = 1286, MAX_M = 128, MAX_L = 60;
const int MAX_LEN = MAX_N * MAX_M * MAX_L;
int MRI[MAX_LEN];
int tot = 0;
int M, N, L, T;

int Union[MAX_LEN];
int count[MAX_LEN];
vector<int> stack(MAX_LEN);

int find(int x){
    stack.clear();
    while(Union[x] != x){
        stack.push_back(x);
        x = Union[x];
    }
    for(int k : stack){
        Union[k] = x;
    }
    return x;
}

void join(int a, int b){
    int fa = find(a);
    int fb = find(b);
    Union[fb] = fa;
    if(fa != fb) count[fa] += count[fb];
}

int main(){
    // ios::sync_with_stdio(false);
    cin >> M >> N >> L >> T;
    auto id = [=](int i, int j, int k){
        return i * N * L + j * L + k;
    };
    for(int k = 0; k < L; k++){
        for(int i = 0; i < M; i++){
            for(int j = 0; j < N; j++){
                cin >> MRI[id(i, j, k)];
                Union[id(i, j, k)] = id(i, j, k);
                if(MRI[id(i, j, k)]) count[id(i, j, k)] = 1;
            }
        }
    }
    for(int k = 0; k < L; k++){
        for(int i = 0; i < M; i++){
            for(int j = 0; j < N; j++){
                if(!MRI[id(i, j, k)]) continue;
                if(i > 0 && MRI[id(i - 1, j, k)]){
                    join(id(i, j, k), id(i - 1, j, k));
                }
                if(i < M - 1 && MRI[id(i + 1, j, k)]){
                    join(id(i, j, k), id(i + 1, j, k));
                }
                if(j > 0 && MRI[id(i, j - 1, k)]){
                    join(id(i, j, k), id(i, j - 1, k));
                }
                if(j < N - 1 && MRI[id(i, j + 1, k)]){
                    join(id(i, j, k), id(i, j + 1, k));
                }
                if(k > 0 && MRI[id(i, j, k - 1)]){
                    join(id(i, j, k), id(i, j, k - 1));
                }
                if(k < L - 1 && MRI[id(i, j, k + 1)]){
                    join(id(i, j, k), id(i, j, k + 1));
                }
            }
        }
    }
    for(int k = 0; k < L; k++){
        for(int i = 0; i < M; i++){
            for(int j = 0; j < N; j++){
                if(!MRI[id(i, j, k)] || find(id(i, j, k)) != id(i, j, k)) continue;
                int c = count[find(id(i, j, k))];
                if(c >= T) tot += c;
            }
        }
    }
    cout << tot << endl;
    // exit(0);
}



发表于 2019-08-20 15:58:09 回复(2)
这段代码在牛客上完美通过了,但是在pta上显示是段错误(可能是数组越界),有没有大佬知道是什么问题?
我用1*2*3的空间,反复排列测试过,没有问题
另外,我不知道为什么那么多人设置成1230,其实你们这里改成128也不会有问题,我觉得原文的意思是切面的面积不超过1286,单个边长度不超过128.

#include <iostream>
#include <string.h>
using namespace std;
#define MAX_COL 130
#define MAX_RAW 61
int arrMap[MAX_RAW][MAX_COL][MAX_COL];
int arrVisit[MAX_RAW][MAX_COL][MAX_COL];
int nVol=0;
int nTotal=0;
int n,m,l;

void dfs(int x,int y,int z)
{
    if (x<l&&x>=0&&y>=0&&z>=0&&y<n&&z<m&&arrVisit[x][y][z]==0&&arrMap[x][y][z]==1)
    {
        arrVisit[x][y][z]=1;
        nVol+=arrMap[x][y][z];
        dfs(x+1,y,z);
        dfs(x,y+1,z);
        dfs(x,y,z+1);
        dfs(x-1,y,z);
        dfs(x,y-1,z);
        dfs(x,y,z-1);
    }
}

int main()
{
    memset(arrMap,0,sizeof(arrMap));
    memset(arrVisit,0,sizeof(arrVisit));
    int t,i,j,k;
    cin>>n>>m>>l>>t;
    for (i=0;i<l;i++)
    {
        for (j=0;j<n;j++)
        {
            for (k=0;k<m;k++)
            {
                cin>>arrMap[i][j][k];
            }
        }
    }
    for (i=0;i<l;i++)
    {
        for (j=0;j<n;j++)
        {
            for (k=0;k<m;k++)
            {
                nVol=0;
                dfs(i,j,k);
                if (nVol>=t)
                {
                    nTotal+=nVol;
                }
            }
        }    
    }
    cout<<nTotal;
    return 0;
}
发表于 2019-08-14 11:21:22 回复(0)
看见没有JAVA的 BFS 没注释,应该能看懂

import java.util.Scanner;
import java.util.LinkedList;
import java.util.Queue;

public class A1004
{
    private static int[][][] slices;
    private static int[][][] visited;
    private static Queue<int[]> BFSqueue;
    private static int M,N,L,T;
    

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        M = sc.nextInt();
        N = sc.nextInt();
        L = sc.nextInt();
        T = sc.nextInt();
        slices = new int[L][M][N];
        visited = new int[L][M][N];
        for(int l =0;l<L;l++)
        {
            for(int m=0;m<M;m++)
            {
                for(int n =0;n<N;n++)
                {
                    slices[l][m][n] = sc.nextInt();
                }
            }
        }
        sc.close();
        int result = 0;
        for(int l =0;l<L;l++)
        {
            for(int m=0;m<M;m++)
            {
                for(int n =0;n<N;n++)
                {
                    if(visited[l][m][n]==0&&slices[l][m][n]==1)
                    {
                        result +=BFS(l,m,n);
                    }
                        
                }
            }
        }
        System.out.print(result);

    }


    private static int BFS(int l, int m, int n)
    {
        int number = 0;
        visited[l][m][n] = 1;
        slices[l][m][n]=0;
        int[] temp = {l,m,n};
        BFSqueue = new LinkedList<>();
        BFSqueue.add(temp);
        number++;
        while(!BFSqueue.isEmpty())
        {
            int[] head = BFSqueue.poll();
            for(int[] i = nextNeighbor(head);i[0]>=0;i=nextNeighbor(head))
            {
                number++;
                BFSqueue.add(i);
            }
        }
        if(number>=T)
            return number;
        else
            return 0;
        
    }


    private static int[] nextNeighbor(int[] head)
    {
        // 上 下 前 后 左 右
        int l = head[0];
        int m = head[1];
        int n = head[2];
        if(l-1>=0&&visited[l-1][m][n]==0&&slices[l-1][m][n]==1)
        {
            int[] temp = {l-1,m,n};
            visited[l-1][m][n]=1;
            slices[l-1][m][n]=0;
            return temp;
        }
        else if(l+1<L&&visited[l+1][m][n]==0&&slices[l+1][m][n]==1)
        {
            int[] temp = {l+1,m,n};
            visited[l+1][m][n]=1;
            slices[l+1][m][n]=0;
            return temp;
        }
        else if(m-1>=0&&visited[l][m-1][n]==0&&slices[l][m-1][n]==1)
        {
            int[] temp = {l,m-1,n};
            visited[l][m-1][n]=1;
            slices[l][m-1][n]=0;
            return temp;
        }
        else if(m+1<M&&visited[l][m+1][n]==0&&slices[l][m+1][n]==1)
        {
            int[] temp = {l,m+1,n};
            visited[l][m+1][n]=1;
            slices[l][m+1][n]=0;
            return temp;
        }
        else if(n-1>=0&&visited[l][m][n-1]==0&&slices[l][m][n-1]==1)
        {
            int[] temp = {l,m,n-1};
            visited[l][m][n-1]=1;
            slices[l][m][n-1]=0;
            return temp;
        }
        else if(n+1<N&&visited[l][m][n+1]==0&&slices[l][m][n+1]==1)
        {
            int[] temp = {l,m,n+1};
            visited[l][m][n+1]=1;
            slices[l][m][n+1]=0;
            return temp;
        }
        int[] temp = {-1,-1,-1};
        return temp;
    
    }


}

发表于 2019-01-26 18:48:47 回复(0)

这里在PAT官网上DFS会爆栈很多人说过了,还有如果数组开的顺序不一样在PAT上一样会TLE(当然调用顺序也改正确的情况下),牛客的话给的时间比较宽裕,我猜测是跟***数组大小的内存连续缓存有关,如果有知道详细的请指教

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
//这里开数组的顺序是mnl,如果是lmn的顺序在PTA官网上会TLE 
int image[1300][200][70],vis[1300][200][70]={0},dir[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}}; 
int m,n,l,t,ans=0;
struct point
{
    int x,y,z;
    point(int x,int y,int z)
    {
        this->x=x;
        this->y=y;
        this->z=z;
    }
};
int bfs(int x,int y,int z)
{
    int num=1;
    vis[x][y][z]=1;
    queue<point> q;
    q.push(point(x,y,z));
    while(!q.empty())
    {
        point p=q.front();
        q.pop();
        for(int i=0;i<6;i++)//每次前后左右上下遍历 
        {
            point next_p=point(p.x+dir[i][0],p.y+dir[i][1],p.z+dir[i][2]);
            if(next_p.x<0||next_p.x>=m||next_p.y<0||next_p.y>=n||next_p.z<0||next_p.z>=l||vis[next_p.x][next_p.y][next_p.z]||image[next_p.x][next_p.y][next_p.z]==0)
                continue;//边界情况跳出 
            vis[next_p.x][next_p.y][next_p.z]=1;//标记为已访问并且联通块数量自增 
            num++;
            q.push(next_p);
        }
    }
    return num;
}
int main()
{
    scanf("%d %d %d %d",&m,&n,&l,&t);
    for(int i=0;i<l;i++)//输入三维图像矩阵 
        for(int j=0;j<m;j++)
            for(int k=0;k<n;k++)
                scanf("%d",&image[j][k][i]);
    for(int i=0;i<l;i++)
        for(int j=0;j<m;j++)
            for(int k=0;k<n;k++)
                if(!vis[j][k][i]&&image[j][k][i])//如果没被访问过并且该点为1的话开始遍历联通块 
                {
                    int num=bfs(j,k,i);
                    if(num>=t)//联通块数量大于t记录 
                        ans+=num;
                }
    printf("%d",ans);
    return 0;
}
编辑于 2019-01-15 15:23:36 回复(0)
dx,dy,dz = [1,-1,0,0,0,0],[0,0,1,-1,0,0],[0,0,0,0,1,-1]
vol,res = [],0
def bfs(z,y,x):
    global res
    ret = 0
    temp = []
    temp.append([z,y,x])
    ret+=1
    vol[z][y][x]=0
    while temp:
        z,y,x = map(int,temp.pop())
        for i in range(6):
            nz = z+dz[i]
            ny = y+dy[i]
            nx = x+dx[i]
            if (nx<n and nx>=0 and ny<m and ny>=0 and nz<l and nz>=0) and vol[nz][ny][nx]==1:
                vol[nz][ny][nx] = 0
                ret+=1
                temp.append([nz,ny,nx])
    if ret>=t:
        res+=ret
m,n,l,t = map(int,input().split())
for k in range(l):
    lst = []
    for j in range(m):
        lst.append(list(map(int,input().split())))
    vol.append(lst)
for k in range(l):
    for j in range(m):
        for i in range(n):
            if vol[k][j][i]==1:
                bfs(k,j,i)
print(res)
参考了大神的思路。贴一个python版本的。注意要节省内存空间。
发表于 2018-12-15 11:43:54 回复(2)
package PAT.advance; import java.util.ArrayList; import java.util.List; import java.util.Scanner;  public class AcuteStroke {  public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);  int M = scanner.nextInt();  int N = scanner.nextInt();  int L = scanner.nextInt();  int T = scanner.nextInt();  int[][][] cores = new int[L][M][N];  int total = 0;  for (int i = 0; i < L; i++) { for (int j = 0; j < M; j++) { for (int k = 0; k < N; k++) {
                    cores[i][j][k] = scanner.nextInt();  }
            }
        } for (int i = 0; i < L; i++) { for (int j = 0; j < M; j++) { for (int k = 0; k < N; k++) { if (cores[i][j][k] == 1) { int local = dfs(cores, i, j, k, L, M, N);  if (local >= T){
                            total += local;  }
                    }
                }
            }
        }
        System.out.println(total);  } static class Point{ int i;  int j;  int k;  Point(int i, int j, int k){ this.i = i;  this.j = j;  this.k = k;  }
    } private static int dfs(int[][][] cores, int i1, int j1, int k1, int L, int M, int N) {
        List<Point> points = new ArrayList<>();  int local = 1;  cores[i1][j1][k1] = 0;  points.add(new Point(i1,j1,k1));  while (points.size()!=0){
            Point point = points.get(0);  points.remove(0);  int i = point.i;  int j = point.j;  int k = point.k;  if(i-1>=0 && cores[i-1][j][k] == 1){
                local++;  cores[i-1][j][k]=0;  points.add(new Point(i-1,j,k));  } if(j-1>=0 && cores[i][j-1][k] == 1){
                local++;  cores[i][j-1][k]=0;  points.add(new Point(i,j-1,k));  } if(k-1>=0 && cores[i][j][k-1] == 1){
                local++;  cores[i][j][k-1]=0;  points.add(new Point(i,j,k-1));  } if(i+1 < L && cores[i+1][j][k] == 1){
                local++;  cores[i+1][j][k]=0;  points.add(new Point(i+1,j,k));  } if(j+1 < M && cores[i][j+1][k] == 1){
                local++;  cores[i][j+1][k]=0;  points.add(new Point(i,j+1,k));  } if(k+1 < N && cores[i][j][k+1] == 1){
                local++;  cores[i][j][k+1]=0;  points.add(new Point(i,j,k+1));  }
        } return local;  }
}
三维数组往三个方向上快速的遍历方法
建立三个数组
for (int i=0;i<6;i++) {
int nx = x + dx[i];
int ny = y + dy[i];
int nz = z + dz[i];
}
得到各个方向的唯一,二维数组相同。

编辑于 2018-09-27 12:57:39 回复(0)
#include<bits/stdc++.h>
using namespace std;
int f[10000005];
int a[61][1289][129];
int vst[10000005];
int sf(int x){
    return x==f[x]?x:f[x]=sf(f[x]);
}
int main(){
    for(int i=1;i<1000005;i++)f[i]=i;
    int m,n,l,t;
    cin>>m>>n>>l>>t;
    for(int i=0;i<l;i++)
    for(int j=0;j<m;j++)
    for(int k=0;k<n;k++)
    scanf("%d",&a[i][j][k]);
    int now,tmp;
    for(int i=0;i<l;i++){
        for(int j=0;j<m;j++){
            for(int k=0;k<n;k++){
                if(a[i][j][k]==0)continue;
                now=i*(m*n)+j*n+k+1;
            //    cout<<i<<" "<<j<<" "<<k<<" "<<now<<endl;
                if(i>0&&a[i-1][j][k]==1){
                    tmp=now-(m*n);
                    f[sf(now)]=sf(tmp);
                }
                if(j>0&&a[i][j-1][k]==1){
                    tmp=now-n;
                    f[sf(now)]=sf(tmp);
                }
                if(k>0&&a[i][j][k-1]==1){
                    tmp=now-1;
                    f[sf(now)]=sf(tmp);
                }
            }}}
    memset(vst,0,sizeof(vst));
    vector<int>v;
    map<int,int>mp;
        for(int i=0;i<l;i++){
        for(int j=0;j<m;j++){
            for(int k=0;k<n;k++){
                if(a[i][j][k]==0)continue;
                now=i*(m*n)+j*n+k+1;
                tmp=sf(now);
                if(vst[tmp])mp[tmp]++;
                else {
                    v.push_back(tmp);
                    mp[tmp]=1;
                    vst[tmp]=1;
                }
            }}}
            int ans=0;
        /*
                for(int i=0;i<l;i++){
        for(int j=0;j<m;j++){
            for(int k=0;k<n;k++){
                cout<<sf(i*(m*n)+j*n+k+1)<<" ";
            }
            cout<<endl;
            
        }
        cout<<endl;
    }
*/
            for(int i=0;i<v.size();i++){
                if(mp[v[i]]>=t)ans+=mp[v[i]];
            }
            cout<<ans;
    return 0;
}
发表于 2018-09-06 18:57:36 回复(0)

问题信息

难度:
25条回答 11095浏览

热门推荐

通过挑战的用户