题意:
给定N个数的序列, 希望将它排列成1~N, 可以用剪切、粘贴来完成任务, 每次可以剪切一段连续的自然段, 粘贴时按照顺序粘贴。
#include <bits/stdc++.h> #define rep(i,a,b) for(int i = a; i < b; i++) #define _rep(i,a,b) for(int i = a; i <= b; i++) using namespace std; const int maxn = 12; int n, maxd; int p[maxn], ans; int h(){//统计每个元素后继不符合的个数, 最后一个特判是否为N int cnt = 0; rep(i,0,n-1) if(p[i+1] != p[i] + 1) cnt++; if(p[n-1] != n) cnt++; return cnt; } bool dfs(int d){ if(d*3 + h() > maxd*3) return false; //由于每次交换最多减少3个后继不符合, 所以当前层数*3 + 上h()大于maxd * 3, 直接剪枝 if(d == maxd){ if(h() == 0) return true; return false; } int b[maxn], old[maxn], cnt = 0; memcpy(old,p,sizeof(p)); rep(i,0,n) //选择起点 rep(j,i,n) //选择终点 , p上取 3个点, i , j , k rep(k,j+1,n){ //由于具有对称性, 直接把前面换到后面就行 memcpy(b,old+i,sizeof(int) * (j-i+1)); //将i~j剪贴的内容复制到b memcpy(p+i,old+j+1, sizeof(int) * (k-j));//将i~j 与 (j+1)~k互换 memcpy(p+i+k-j, b, sizeof(int) * (j-i+1)); if(dfs(d+1)) return true; memcpy(p,old,sizeof(old)); } return false; } int main(){ int kase = 0; while(cin >> n && n){ rep(i,0,n) cin >> p[i]; for(maxd = 0; maxd <= 5; maxd++){ //注意maxd要从0开始, 因为有可能一开始就是有序的 if(dfs(0)) break; } cout << "Case " << ++kase << ": " << maxd << "\n"; } }
原文地址:https://www.cnblogs.com/Jadon97/p/8324038.html
时间: 2024-11-09 02:17:26