一道暴力的题,但暴力的过程中约束太多,必要的剪枝也太多了,所以我也不知道到底这道题属于什么了,不过这题还有状态压缩的做法,我会在下一篇博客上写(其实我看这道题本意是看状态压缩的)
题解全在代码的注释里了我就不再打一遍了。
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 ",b[i]); 52 ans=11111111; 53 dfs(1,0); 54 printf("%d ",ans); 55 } 56 57 }