资讯详情

算法-连通core的电阻-dfs

文章目录

  • 题意
    • 样例
  • 分析
    • 参考题解1
    • 参考题解2
    • 参考题解3

题意

芯片二维平面图是一个n*n二维矩阵(0<n<300),其中: 0表示core -1表示路径不通 其他正数表示电阻 路径电阻计算是路径上最大的电阻值。

- - - -
14
-1
7 -1 -1
3

上面4*4矩阵中的加粗数,4个core(0)连接。路径电阻为4。

0<n<300 core数量小于100,大于0

样例

输入: 3 (n=3) 0 1 3 -1 2 1 0 1 1 输出: 2

分析

算出每个core到core0电阻,取最大值,即可。

题解1: 自归函数,自上而下

题解2: 递归函数,自底向上,9万次调用,栈溢出

非典型的DAG图,DP方法,刷表从头到尾都做不到。 因此,将更新的节点存储在队列中,刷新受影响的节点,直到收敛。 题解3: DP自底向上刷表

参考题解1

#include<stdio.h> #define MIN(a,b) (a)<(b)?(a):(b) #define MAX(a,b) (a)>(b)?(a):(b) int N, coreNum;       ///矩阵范围N,核心数coreNum int chip[300][300];    int core[100][2];     //记录核心坐标 int dir[4][2] = { 
         { 
        1,0},{ 
        0,1},{ 
        -1,0},{ 
        0,-1} };
//坐标xy到核心0的路径电阻。4代表从哪个方向递推来的
//因为有时候visit标记导致某个方向continue了
//所以必须要4个方向都递推过,坐标xy的路径电阻才能确认,然后才能使用memo
int memo[300][300][4] = { 
        0};
bool visit[300][300] = { 
         0 };
void input();
bool illeagle(int x, int y)
{ 
        
	if (x < 0 || y < 0)
		return false;
	if(x > N-1 || y > N - 1)
		return false;
	if (chip[x][y] == -1)
		return false;
	return true;
}
int dfs(int x, int y)  //坐标xy到核心0的最小路径电阻
{ 
        
	int i, nextx, nexty;
	int tmp = INT_MAX;
	if (core[0][0] == x && core[0][1] == y)
		return 0;
	if (memo[x][y][0] != 0 &&
		memo[x][y][1] != 0 &&
		memo[x][y][2] != 0 &&
		memo[x][y][3] != 0)
	{ 
        
		//4个中最小的
		return MIN(MIN(MIN(memo[x][y][0], memo[x][y][1]), memo[x][y][2]), memo[x][y][3]);
	}
	for (i = 0; i < 4; i++)
	{ 
        
		nextx = x + dir[i][0];
		nexty = y + dir[i][1];
		if (memo[nextx][nexty][i] != 0)
		{ 
        
			tmp = MIN(tmp, memo[nextx][nexty][i]);
			continue;
		}
		if (false==illeagle(nextx, nexty))
		{ 
        
			memo[nextx][nexty][i] = INT_MAX;
			continue;
		}
		if (visit[nextx][nexty] == true)
			continue;
		visit[nextx][nexty] = true;
		memo[nextx][nexty][i] = dfs(nextx, nexty);
		visit[nextx][nexty] = false;
		tmp = MIN(tmp, dfs(nextx, nexty));
	}
	return MAX(tmp, chip[x][y]);
}
/* 3 0 1 3 -1 2 1 0 1 1 5 0 1 1 3 2 -1 -1 2 0 6 -1 -1 5 1 7 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 */
int main()
{ 
        
	int i, j;
	int res = 0;
	input();
	for (i = 1; i < coreNum; i++) //计算每个core到0号core的电阻,取最大值
	{ 
        
		visit[core[i][0]][core[i][1]] = true;
		res = MAX(res, dfs(core[i][0], core[i][1]));
		visit[core[i][0]][core[i][1]] = false;
	}
}
void input()
{ 
        
	int i = 0; int j = 0;
	coreNum = 0;
	scanf("%d", &N);
	for (i = 0; i < N; i++)
	{ 
        
		for (j = 0; j < N; j++)
		{ 
        
			scanf("%d", &chip[i][j]);
			if (chip[i][j] == 0)
			{ 
        
				core[coreNum][0] = i;
				core[coreNum][1] = j;
				coreNum++;
			}
		}
	}
}

参考题解2

#include<stdio.h>
#define MIN(a,b) (a)<(b)?(a):(b)
#define MAX(a,b) (a)>(b)?(a):(b)
int N, coreNum;       //矩阵范围N,核心数coreNum
int chip[300][300];
int core[100][2];     //记录核心的坐标
int dir[4][2] = { 
         { 
        1,0},{ 
        0,1},{ 
        -1,0},{ 
        0,-1} };
int memo[300][300] = { 
        0};
void input();
bool illeagle(int x, int y)
{ 
        
	if (x < 0 || y < 0)
		return false;
	if(x > N-1 || y > N - 1)
		return false;
	if (chip[x][y] == -1)
		return false;
	return true;
}
void updated(int x, int y)
{ 
        
	int i = 0;
	int nextx, nexty;
	int memonext;
	for (i=0;i<4;i++) //xy更新了,遍历xy四周的4个点尝试被更新
	{ 
        
		nextx = x + dir[i][0];
		nexty = y + dir[i][1];
		if (true==illeagle(nextx, nexty))
		{ 
        
		    //nextxy 到core0的路径值比xy大,可以更新一下。
		    //更新为chip[nextx][nexty]或者memo[x][y]。
			memonext = MAX(MIN(memo[nextx][nexty], memo[x][y]), chip[nextx][nexty]);
			if (memonext!= memo[nextx][nexty])
			{ 
        
				memo[nextx][nexty] = memonext;
				updated(nextx, nexty);//nextx真的更新了,就要更新nextx周围的点
			}
		}
	}
}
/* 3 0 1 3 -1 2 1 0 1 1 5 0 1 1 3 2 -1 -1 2 0 6 -1 -1 5 1 7 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 */
int main()
{ 
        
	int i, j;
	int res = 0;
	input();
	memo[core[0][0]][core[0][1]] = 0;
	updated(core[0][0], core[0][1]); //0号core的坐标开始更新,影响4周的4个点
}
void input()
{ 
        
	int i = 0; int j = 0;
	coreNum = 0;
	scanf("%d", &N);
	for (i = 0; i < N; i++)
	{ 
        
		for (j = 0; j < N; j++)
		{ 
        
			scanf("%d", &chip[i][j]);
			if (chip[i][j] == 0)
			{ 
        
				core[coreNum][0] = i;
				core[coreNum][1] = j;
				coreNum++;
			}
			memo[i][j] = INT_MAX;
		}
	}
}

参考题解3

#include<stdio.h>
#define MIN(a,b) (a)<(b)?(a):(b)
#define MAX(a,b) (a)>(b)?(a):(b)
int N, coreNum;       //矩阵范围N,核心数coreNum
int chip[300][300];
int core[100][2];     //记录核心的坐标
int dir[4][2] = { 
         { 
        1,0},{ 
        0,1},{ 
        -1,0},{ 
        0,-1} };
int memo[300][300] = { 
        0};
#define quelen (300*300)
int queue[quelen] = { 
        0};
bool inqueue[300][300] = { 
         0 };
void input();
bool illeagle(int x, int y)
{ 
        
	if (x < 0 || y < 0)
		return false;
	if(x > N-1 || y > N - 1)
		return false;
	if (chip[x][y] == -1)
		return false;
	return true;
}
/* 3 0 1 3 -1 2 1 0 1 1 5 0 1 1 3 2 -1 -1 2 0 6 -1 -1 5 1 7 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 10 12 5 7 3 4 13 1 5 10 17 13 19 18 5 2 9 11 7 15 15 11 16 20 12 8 4 1 9 16 13 7 5 14 12 16 0 11 10 16 19 2 1 11 4 19 7 12 12 1 9 10 3 15 0 14 19 4 18 12 14 20 6 7 9 3 12 4 11 15 20 1 1 6 6 2 14 6 7 4 17 16 13 12 4 13 4 5 3 19 13 6 12 3 5 0 12 0 10 20 17 */
int main()
{ 
        
	int i, j;
	int head = 0;
	int tail = 0;
	int x, y;
	int nextx, nexty, memonext;
	int tmp;
	input();
	memo[core[0][0]][core[0][1]] = 0;
	//从core0开始,core0坐标放入队列
	queue[tail++] = core[0][0] * N + core[0][1];
	inqueue[core[0][0]][core[0][1]] = true;
	while (tail!=head) //队列非空,有memo更新了,尝试更新周围的点
	{ 
        
		tmp = queue[head++];  //取出一个点
		head = head % quelen;
		x = tmp / N;
		y = tmp % N;
		inqueue[x][y] = false;
		for (i = 0; i < 4; i++) //更新这个点四周的点
		{ 
        
			nextx = x + dir[i][0];
			nexty = y + dir[i][1];
			if (true == illeagle(nextx, nexty))
			{ 
        
				memonext = MAX(MIN(memo[nextx][nexty], memo[x][y]), chip[nextx][nexty]);
				if (memonext != memo[nextx][nexty])
				{ 
        
					memo[nextx][nexty] = memonext;
					//nextx更新了,把它放到队列
					if (inqueue[nextx][nexty] == false)
					{ 
        
						queue[tail++] = nextx * N + nexty;
						tail = tail % quelen;
						inqueue[nextx][nexty] = true;
					}
				}
			}
		}
	}
}
void input()
{ 
        
	int i = 0; int j = 0;
	coreNum = 0;
	scanf("%d", &N);
	//N = 299;
	for (i = 0; i < N; i++)
	{ 
        
		for (j = 0; j < N; j++)
		{ 
        
			//chip[i][j] = rand() % 10;
			//if (chip[i][j] > 8 || (chip[i][j]==0 && coreNum==100))
			// chip[i][j] = -1;
			scanf(

标签: dp840用电阻

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台