题目大意:图的着色问题。给定一个无向图(不一定连通),给图中的点涂上黑白两种颜色,但相邻的两个点不能全是黑色。任务是算出最多可以涂上几个黑点。
解题思路:依次判断每个点能不能涂成黑色,然后会有三种情况(就是这三条路,沿着这三条路一直往下遍历,就ok)
第一条:如果邻接点已经有了黑点,则改点不能再涂黑色了,直接往下遍历即可,这是一条路,与后面的两条路没有牵扯,所以后面加上return表示一种情况;
第二条和第三条:如果邻接点没有黑点,那么改点的涂法就可以有两种,每种都要遍历一下,继续往下走即可。
注意自己控制好边界条件。
#include <stdio.h> #include <string.h> #include <stdlib.h> int G[110][110]; int color[110]; int ans[110]; int n,m; int max_; void dfs(int cur,int black_num) { if(cur > n) { if(black_num>max_) { max_=black_num; memcpy(ans,color,sizeof(color)); } return; } for(int v = 1;v<=n;v++) { if(G[cur][v]&&color[v]) { dfs(cur+1,black_num); return; } } color[cur]=1; dfs(cur+1,black_num+1); color[cur]=0; dfs(cur+1,black_num); } int main() { int t; scanf("%d",&t); while(t--) { memset(G,0,sizeof(G)); memset(color,0,sizeof(color)); scanf("%d%d",&n,&m); int a1,a2; for(int i=0;i<m;i++) { scanf("%d%d",&a1,&a2); G[a1][a2]=G[a2][a1]=1; } max_=0; dfs(1,0); printf("%d\n",max_); int flag=0; for(int i=1;i<=n;i++) { if(ans[i]) { if(flag) printf(" "); printf("%d",i); flag=1; } } printf("\n"); } return 0; }
这道题算很简单的回溯题目,却断断续续做了三次没有能AC,最后还是看了题解,然后马上就有了一条非常清晰的思路。简单利落的写出来,然后一遍过掉。
为什么前两次做的时候会那么迷茫地用错误的思路得到同样的wrong?这是值得我深思的。
一方面因为自己读题的时候就没能完全把握住题意,对题目所给出的任务并不明确。造成这种结果的原因,并不能简单归咎于英语问题的不大好理解。通过昨天的校内赛,再加上自己之前的总结,可以明确地告诉自己,对任务的准确和快速把握,是练ACM的强大技能之一。在这一方面,并不是你的英语好你就占尽优势,因为对所给任务的把握,你应该综合各方面的信息。比如,你需要找准题目描述中哪段话告诉的哪段信息是对自己有用的,时透露给自己某种边界信息,或是对自己解题思路的形成有一定的指导作用,这项技能需要你做大量的题目,从中寻找灵感,发现规律,或是神奇的就是会有某种感觉。然后是你对所给样例的揣摩,有些题目有些人可以直接不看题目而从样例中明白任务的具体内容,从而快速Ac题。对于我们来说,即使不能看样例做题,也一定能从样例中获得不可忽视的启发,对解题思路的形成会有巨大帮助。
另外一个比较神的说法就是自己对题目的感觉,也许你不知道为什就会有这种感觉,可你就是有这种感觉。我就觉得这道题这样来干就能AC,那你就这样去干。
总之,准确获取任务很重要,任务不明确你还费什么功夫呢?下了功夫,也是越来越迷茫~。