[2016-02-27][UVA][11212][Editing a Book]
- 时间:2016-02-26 19:38:44 星期五
- 题目编号:UVA 11212
- 题目大意:给定长度为n(值为1~n)的序列,求把该序列 复制/粘贴 成1~n 的排列最少步数
- 分析:
- 状态空间搜索,但是每次状态转移的方式有多种,可能会T,
- 发现,最多 操作 的次数:n~1的序列,每次操作 长度为1的连续段,那么需要 n-1 次操作
- 可以用IDA*算法
- 剪枝,每次操作之后,每个数字的后继数字不正确的数目h,最多减少3,
- 那么至少需要 h / 3 次操作才能,达到目标
- 方法:IDA*
- 数据是10个长度,所以,结贴操作直接for语句完成
- dfs过程,层数达到maxd,判断是否排列好
- 如果预测最少层数大于maxd,直接返回
- dfs ,枚举起点和宽度,截取这一段数字,放在起点前面任意一个点,然后进入下层dfs
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; typedef long long LL; #define CLR(x,y) memset((x),(y),sizeof((x))) #define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x)) #define FORD(x,y,z) for(int (x)=(y);(x)>=(z);--(x)) #define FOR2(x,y,z) for((x)=(y);(x)<(z);++(x)) #define FORD2(x,y,z) for((x)=(y);(x)>=(z);--(x)) const int maxn = 11; int x[maxn],n,a[maxn]; int is_sorted(){ FOR(i,0,n) if(a[i] != i + 1) return 0; return 1; } int h(){ int cnt = 0; FOR(i,0,n - 1){ if(a[i] + 1 != a[i + 1]) ++cnt; } return cnt; } int dfs(int curcnt,int & maxd){ //成功返回1,同时结束bfs if(curcnt == maxd) return is_sorted(); //超过范围 if(curcnt*3 + h() > 3 * maxd) return 0; int tmp[maxn]; memcpy(tmp,a,sizeof(int)*n); FOR(i,1,n){//枚举长度 for(int j = 0; i + j - 1 < n;++j){//枚举起点 //剪切 区段 int t1[maxn],t2[maxn],c1 = -1,c2 = -1; FOR(k,0,n){ if( k >= j && k < i + j) t1[++c1] = tmp[k]; else t2[++c2] = tmp[k]; } //粘贴区段 FOR(k,0,j){ int c = -1; FOR(l,0,k) a[++c] = t2[l]; FOR(l,0,c1+1) a[++c] = t1[l]; FOR(l,k,c2+1) a[++c] = t2[l]; //进入下层dfs if(dfs(curcnt + 1,maxd)) return 1; } } } return 0; } int main(){ int cntcase = 0; while(~scanf("%d",&n) && n){ FOR(i,0,n) scanf("%d",x+i); int i; //枚举步骤数目, for(i = 0;;++i){ memcpy(a,x,sizeof(int)*n); if(dfs(0,i)) break; } printf("Case %d: %d\n",++cntcase,i); } return 0; } |