HDU1584(子集生成问题,dfs)

一道暴力的题,但暴力的过程中约束太多,必要的剪枝也太多了,所以我也不知道到底这道题属于什么了,不过这题还有状态压缩的做法,我会在下一篇博客上写(其实我看这道题本意是看状态压缩的)

题解全在代码的注释里了我就不再打一遍了。

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<math.h>
 4 #include<string.h>
 5 using namespace std;
 6 ///子集生成问题,寻找最优子集,暴力的知识,涉及最优子集生成和最优子集打印两种出题方式,方法是按照层数进行搜素,需注意的是复位
 7 int vis[11];///表示搜索到的层数
 8 ///这不是简单的子集生成,题意是只能放到比他大的上面呜呜,找了好久才发现~~~~(>_<)~~~~
 9  ///sum+=abs(b[j]-b[i]这是错的,会改变sum复位的问题
10 int a[11],b[11],c[11];
11 int ans;
12 int cmp(int i,int j){
13     return a[i]<a[j];
14 }
15 void dfs(int cur,int sum){///无需返回值,要一直比较到结束
16     if(sum>=ans) return ;///最大化的剪枝同时省去了结束判定问题太妙了
17     if(cur==10){
18         ans=sum;
19         return ;
20     }
21     for(int i=1;i<10;i++){
22         if(!vis[i]){
23             vis[i]=1;
24             for(int j=i+1;j<=10;j++){
25                 if(!vis[j]){///如果此输已经被放过了那他一定被放到了下一个上面,如果没有说明也被放到下一个了
26                     dfs(cur+1,sum+abs(b[i]-b[j]));
27                     break;///找到下一个别放置的真正位置计算位置不能越位放置
28                 }
29             }
30             vis[i]=0;
31         }
32     }
33 }
34 int main(){
35     int n;
36     scanf("%d",&n);
37     while(n--){
38         for(int i=1;i<=10;i++)
39             scanf("%d",&a[i]);
40         for(int i=1;i<=10;i++)
41             b[i]=i;
42         memset(vis,0,sizeof(vis));
43         ///可以用下面的的等价,而且更加简单好实现好理解
44         /*for(int i=1;i<=10;i++){
45             int temp;
46             scanf("%d",temp);
47             a[temp]=i;
48         }*/
49         sort(b+1,b+11,cmp);
50         ///for(int i=1;i<=10;i++)
51        /// printf("b=%d\n",b[i]);
52         ans=11111111;
53         dfs(1,0);
54         printf("%d\n",ans);
55     }
56 
57 }

 

posted @ 2016-03-12 10:47  Alan2  阅读(345)  评论(0编辑  收藏  举报