【题解】CF2232D
0
1:如何解决普通汉诺塔
分治递归
2:普通汉诺塔和这个汉诺塔的区别
当所有 \(a_i=0\) 时,为普通汉诺塔
3:类比
模仿普通汉诺塔的解决办法
如果 \(a_i=0\) ,按照普通汉诺塔做
否则分成 \([1,n-1-a_i][n-a_i,n-1][n,n]\) 三部分,分治处理即可
4:复杂度分析
复杂度是否为 \(O(2^n)\),即证明对于每个 \(n\) 是否满足 \(f(n)<=2^n\)
数学归纳法
起始
对于 \(n=0\) ,显然 \(f(0)<=2^0=1\)
推广
设 \(n\) 满足 \(f(n)<=2^n\)
分两种情况讨论
当 \(a_{n+1}=0,f(n+1)=f(n)+f(n)<=2^{n+1}\)
当 \(a_{n+1}!=0,f(n+1)=2 \times f(n-a_{n+1})+f(n)<=2 \times f(n)<=2^{n+1}\)
证毕
5:代码
// Problem: D. Magical Tiered Cake
// Contest: Codeforces - Codeforces Round 1101 (Div. 2)
// URL: https://codeforces.com/contest/2232/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=22;
int a[N];
struct node{
int a,b,c;
};
vector<node> ans;
void dfs(int n,int A,int B,int C){//把n个环,从A借助B到C
if(n==0) return ;
if(!a[n]){
dfs(n-1,A,C,B);
ans.push_back({n,A,C});
dfs(n-1,B,A,C);
}
else{
dfs(n-1-a[n],A,C,B);
ans.push_back({n,A,C});
dfs(n-1-a[n],B,C,A);
dfs(n-1,A,B,C);
}
}
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
if(a[i]>=i){
cout<<"No\n";
return ;
}
}
cout<<"Yes\n";
ans.clear();
dfs(n,1,2,3);
cout<<ans.size()<<"\n";
for(auto v:ans) cout<<v.a<<" "<<v.b<<" "<<v.c<<"\n";
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--) solve();
return 0;
}
6:历程
看到数据范围果断想到状压,于是尝试设计状态,设计状态数为 \(2^{2n}\) 过大,无法记忆化搜索,做不出来
7:反思与评价
7.1
数据范围小不一定是状压,有可能是搜索
7.2
要类比之前学过的知识点,写过的题,会很有帮助

浙公网安备 33010602011771号