您的位置:首页 > 其它

POJ1015 Jury Compromise dfs的实现

2015-12-27 13:31 387 查看
做ACM练习题目已经两个年头了,最开始脑子很混乱,后来慢慢有了感觉,AC率也大幅度提高,接下来就一些经典问题做一下回顾,这些问题涵盖了算法的多个方面,相对来说有一些较为全面的总结,也是我这些年劳动成果的一些体现,今天带来的是另一道经典题目1015的dfs实现。

首先需要说明的是,这道题系统要求是用动态规划来做,并且只有动态规划能够在规定时间内跑完。这里我要说的是dfs的实现,这种实现是不能AC的,但是算法是对的,结果也是对的。之所以不能AC还要写出来,一是因为这道题目的动态规划算法已经有其他博主提供,第二是本题的动态规划算法非常复杂,一般很难想到,可以说一般参赛选手拿到题目首先想到的应该是深搜,虽然我的这套代码不能AC,但也可以作为一种算法的学习,毕竟做题不单单是为了AC,也是为了总结。

一般来说深搜有几种方法:

1.使用堆栈,stack,每循环一次将变量放入stack中,while(!s.empty()),当栈中无数据循环结束;

2.使用还原现场的方法,嵌套递归:

ifVisited[i]=true;//设置记号
execute();//进入下一步递归
ifVisited[i]=false;//还原现场


3.直接使用循环嵌套递归:


if(current==maxSize){
......
}
for(i=current+1;i<=maxSize;i++){
execute(i);
}


本题我们采用的是第三种方式。

dfs(int tp,int td,int already,int start,int *tc)

是我们的递归函数,其中tp指已经选择的那些候选者的正方赞成票,td指反方赞成票,already指已经选择了多少个候选者,和上面的current相似。start代表从第start个候选者往后选,因为之前的已经遍历过了,tc是临时数组,用于存储已经选了哪些候选者。

这道题目可以作为第三种深搜方式很好的学习例子。

#include<iostream>
#include<cmath>

using namespace std;

int n,m;
int d[201],p[201];
int c[21];
int pNum,dNum;

void dfs(int tp,int td,int already,int start,int *tc){
if(already==m){
if(abs(td-tp)<abs(pNum-dNum)){
pNum=tp;
dNum=td;
for(int i=1;i<=m;i++){
c[i]=tc[i];
}
return;
}
else if(abs(td-tp)==abs(pNum-dNum)&&(td+tp)>(pNum+dNum)){
pNum=tp;
dNum=td;
for(int i=1;i<=m;i++){
c[i]=tc[i];
}
return;
}
else{
return;
}
}
if(m-already>n-start){
return;
}
for(int i=start+1;i<=n;i++){
tc[already+1]=i;
dfs(tp+p[i],td+d[i],already+1,i,tc);
}
return;
}

void calc(){
pNum=201;
dNum=-201;
int tc[21];
for(int i=1;i<=n;i++){
tc[1]=i;
dfs(p[i],d[i],1,i,tc);
}
}

int main(){
int totalCase=0;
cin>>n>>m;
while(n!=0){
totalCase++;
for(int i=1;i<=n;i++){
cin>>p[i]>>d[i];
}
calc();
cout<<"Jury #"<<totalCase<<endl;
cout<<"Best jury has value "<<pNum<<" for prosecution and value ";
cout<<dNum<<" for defence:"<<endl;
for(int i=1;i<=m;i++){
cout<<" "<<c[i];
}
cout<<endl;
cin>>n>>m;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: