2011.11.23 POJ2531解题报告【谨以此文,纪念自己跨过POJ50道题的小里程碑】

一,做题状况:

这几天一直处于低谷状态,是因为50题的小坎来了么?呵呵

做题目都没什么思路,看完别人的解题报告后,豁然开朗,哦,明白了,想起来了。。。

归根结底,自己学的不牢固啊,例如这几天的DFS,很多时候看完题才知道,原来这道题目可以用DFS啊。刚开始看题的时候,根本想不到用DFS,就算想到了DFS,也不知道怎么用,总觉得有点模糊不清,还是基础不牢靠吧。

这道题,知道用DFS后,想到用DFS枚举全排列,本来准备马上开始写了,但是决定还是先看看别人的代码。果然啊,如果按照我之前的写法,肯定150行左右的代码量了,而且写完后估计还要调试,各种错误之类问题。 而看完前辈的代码后,终于感觉到了什么叫做精炼的代码。最后50行就可以AC了。


二、思路分析DFS

三、题目类型:DFS,连回溯都没有。网上有人说可以剪枝,但是我始终没想到怎么个剪枝法,因为没法提前找到不符合的路线。

四、进步:

1.明白了,很多时候题目要靠我们用毅力去想,去思考。否则,做题的印象肯定不深刻,效果也不佳。

2.代码要向别人学习,学习写精炼的代码,一方面速度快,另外一方面,健壮性强。 前段时间老是抱怨自己,虽然能AC,但是发现自己的代码长度老师比前面AC的人长很多,甚至有别人两倍那么长,觉得自己写的代码肯定没什么风格,太不精练了。又不知如何成长,其实多多看牛人的源码是由很大好处的。

3.思维要开阔,做题的时候不要急于CODING,很多时候,花几分钟的时间想想数据结构怎么组织,往往会给后期CODING带来巨大的好处,磨刀不误砍柴工,前期思路,数据结构想得好,最后CODING起来也省事,也不需要不断的DEBUG,遇到昨天那道题。 昨天那道题POJ2351,真是让我受益匪浅,很多时候,你采取的数据的表示方式采取得好的话,做起来,何止是事半功倍啊? 远远超出自己的想想。 beyond your expectation!


五源码:

方法一 248K 1360MS VS 方法二 248K  407MS

方法一优点:思路简洁明了,缺点:在DFS终点上用到了复杂度O(n^2)

方法二优点:复杂度只是O(n)(不考虑递归的复杂度),只是算法理解起来比方法一稍微绕一点点,其实只要认真看一遍,就明白了。

//方法一 248K 1360MS
//AC
#include <iostream>
using namespace std;


const int MAX_N = 21;
int N;
int graph[MAX_N][MAX_N];
bool InFirstClass[MAX_N];
int answer;


void dfs(int depth)
{
if( depth == N )
{
int sum = 0;
for(int i=0; i<N; ++i)
{
for(int j=i+1; j<N; ++j)
if( InFirstClass[i] != InFirstClass[j] )
sum += graph[i][j];
}
if( sum > answer )
answer = sum;
return;
}
InFirstClass[depth] = true;
dfs(depth+1);
InFirstClass[depth] = false;
dfs(depth+1);
}


int main()
{
//freopen("data.txt","r",stdin);
cin>>N;
for(int i=0; i<N; ++i)
{
for(int j=0; j < N; ++j)
cin>>graph[i][j];
//InFirstClass[i] = false;  //其实这个没必要初始化
}
answer = 0;
InFirstClass[0] = true;
dfs(1);
cout<<answer<<endl;
return 0;
}


//方法二 248K 407MS
//AC
#include <iostream>
using namespace std;


const int MAX_N = 21;
int N;
int graph[MAX_N][MAX_N];
bool InFirstClass[MAX_N];
int answer;


void dfs(int depth,int sum)
{
if( depth == N )
{
if( sum > answer )
answer = sum;
return;
}
//初步考虑这是第1集合的,那么把前面第2集合到这个点的距离都加起来
int temp = 0;
for(int i=0; i<depth; ++ i)
if( !InFirstClass[i] ) 
temp += graph[i][depth];
InFirstClass[depth] = true;
dfs(depth+1,sum+temp);
//现在考虑这是第1集合的,那么把前面第2集合到这个点的距离都加起来
temp = 0;
for(int i=0; i<depth; ++ i)
if( InFirstClass[i] ) 
temp += graph[i][depth];
InFirstClass[depth] = false;
dfs(depth+1,sum+temp);
}


int main()
{
//freopen("data.txt","r",stdin);
cin>>N;
for(int i=0; i<N; ++i)
{
for(int j=0; j < N; ++j)
cin>>graph[i][j];
//InFirstClass[i] = false;
}
answer = 0;
InFirstClass[0] = true;
dfs(0,0);
cout<<answer<<endl;
return 0;
}


好了,谨以此文,纪念自己跨过POJ50道题的小里程碑。(虽然第50道题不是完全我的创意,是我从他人那里学习到的。其实前面的题,也有很多。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值