[AHOI2012]铁盘整理

题目描述

输入输出格式

输入格式:

共两行。第一行为铁盘个数N(1<=N<=50),第二行为N个不同的正整数,分别为从上到下的铁盘的半径R。(1<=R<=100)

输出格式:

一个正整数,表示使铁盘从小到大有序需要的最少翻转次数。

输入输出样例

输入样例#1:
5
2 4 3 5 1
输出样例#1:
5

迭代加深+A*剪枝
把原序列离散后,目标序列是单调递增且相邻为1的序列
每一次规定一个次数
显然对于一个序列,至少要交换相邻不为1的数字个数
如果加上这个次数大于规定次数就退出
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node
 7 {int x,id;
 8 }a[1001];
 9 int s[1001],ans,n;
10 bool cmp(Node a,Node b)
11 {
12   return a.x<b.x;
13 }
14 int count()
15 {int tot=0,i;
16   for (i=1;i<=n;i++)
17     if (abs(s[i+1]-s[i])!=1) tot++;
18   return tot;
19 }
20 void dfs(int k,int cnt)
21 {int i,j;
22   int l=count();
23   if (l==0&&s[1]<s[2])
24     {ans=k;return;}
25   if (ans||k+l>cnt||k==cnt) return;
26   for (i=2;i<=n;i++)
27     {
28       if (abs(s[i]-s[i+1])==1) continue;
29       for (j=1;j<=i/2;j++)
30     {
31       swap(s[j],s[i-j+1]);
32     }
33       dfs(k+1,cnt);
34       for (j=1;j<=i/2;j++)
35     {
36       swap(s[j],s[i-j+1]);
37     }
38     }
39 }
40 int main()
41 {int i,cnt;
42   cin>>n;
43   for (i=1;i<=n;i++)
44     {
45       scanf("%d",&a[i].x);
46       a[i].id=i;
47     }
48   sort(a+1,a+n+1,cmp);
49   for (i=1;i<=n;i++)
50     s[a[i].id]=i;
51   s[n+1]=n+1;
52   cnt=0;
53   while (!ans)
54     {
55       dfs(0,cnt);
56       cnt++;
57     }
58   cout<<ans;
59 }

 

posted @ 2017-09-23 19:33  Z-Y-Y-S  阅读(410)  评论(0编辑  收藏  举报