【题解】CF2232D

0

\(link\)

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

要类比之前学过的知识点,写过的题,会很有帮助

posted @ 2026-06-04 18:40  Aistyr  阅读(16)  评论(0)    收藏  举报