0x20 搜索

好吧,我前两篇(0x00基本算法,0x10基本数据结构)都写得不太好,因为是前两天做的题有些遗忘,而且为了赶完博客一会儿就写好了,确实有很多漏洞。我应该在一开始就记录自己的学习历程的。不管怎样,接下来的博客我会伴随看书一起进行。

0x20 搜索

0x21 树与图的遍历
例题(自己找的):Luogu P1038 神经网络

太多细节要注意了……做完后的心情就跟吔了屎一样
当然也是因为自己太菜了才会遇到这么多错误

  • 首先想到用拓扑排序,分层维护出每个点的状态(c数组)。
  • 一定要理解公式。维护每个点的状态时,应该先求出该点的入度的状态乘以边权之和,即WjiCj,再减去该点的阈值即Ui。而我却在每次加上WjiCj时都减了该点的Ui值看,导致其被减多了。
  • 建边时要维护每个点的入度(in数组),出度(out数组)。输入点入度为零,输出点出度为零。输入点可能有阈值,但我们应该在求其他点状态时才减去阈值,所以要加个判断,非输入点才减去阈值。
  • 当一个点的状态大于零时才能给下面的点发信号,但判断语句不能在该点出队时就加上,因为会导致与它相连的点的入度值不能更新,所以只在更新下面的点时加一个判断。
  • 注意答案是输出层大于零的状态。
  • 判断一个值x是否大于零时要用"x>0","!x"是指x非零,而不是非负。
#include
using namespace std;

const int maxn=2000;
int n,p,cnt;
int c[maxn],h[maxn],in[maxn],inq[maxn],head[maxn],f[maxn],out[maxn];

struct edge
{
   
	int v,nxt,w;
}e[maxn];

void add(int u,int v,int w)
{
   
	e[++cnt].nxt=head[u];
	e[cnt].v=v;
	e[cnt].w=w;
	head[u]=cnt;
}

void bfs()
{
   
	queue<int>q;
	for(int i=1;i<=n;i++)
		if(!in[i]) 
		{
   
			f[i]=1;
			q.push(i);
		}
	while(!q.empty())
	{
   
		int u=q.front();
		if(!f[u]) c[u]-=h[u];
		q.pop();
		for(int i=head[u];i;i=e[i].nxt)
		{
   
 			int v=e[i].v,w=e[i].w;
			--in[v];
			if(c[u]>0) c[v]+=c[u]*w;
			if(!in[v]&&!inq[v])
			{
   
				inq[v]=1;
				q.push(v);
			}
		}
	}
}

int main()
{
   
	//freopen("input.txt","r",stdin);
	scanf("%d%d",&n,&p);
	for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&h[i]);
	for(int x,y,z,i=1;i<=p;i++)
	{
   
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		++in[y];++out[x];
	}
	bfs();
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
   
		if(c[i]>0&&!out[i])
		{
   
			printf("%d %d\n",i,c[i]);
			++cnt;
		}
	}
	if(!cnt) printf("NULL");
	return 0;
}
0x22 深度优先搜索
例题 小猫爬山

搜索回溯,当前答案大于已得答案时剪枝。

#include
using namespace std;

const int inf=0x3f3f3f3f;
int n,m,ans;
int v[500],c[500];

void dfs(int num,int tot)
{
   
	if(tot>=ans) return;
	if(num>n)//注意是大于,因为num=0时多跑了一遍
	{
   
		ans=min(ans,tot);
		return;
	}
	for(int i=1;i<=tot;i++)
	{
   
		if(v[i]+c[num]>m) continue;
		v[i]+=c[num];
		dfs(num+1,tot);
		v[i]-=c[num];
	}
	v[tot+1]=c[num

你可能感兴趣的:(《算法竞赛进阶指南》)