這是我目前因為TLE修改的程式碼,但改了以後更後面的測資依然TLE:
#include <iostream>
using namespace std;
int count2 = 0;
bool flag = false;
void Towers(int n,char a,char b,char c, int i);
int main() {
int n, i;
cin >> n >> i;
Towers(n,'1','2','3', i);
cout << "\n";
return 0;
}
void Towers(int n,char a,char b,char c, int i){
if(n==1){
if (flag == true){
return;
}
if (count2 == i-1){
cout<<"move "<<n<<" from "<<a<<" to "<<c<<endl;
flag = true;
}
count2++;
}
else{
if (flag == true){
return;
}
Towers(n-1,a,c,b, i);
if (count2 == i-1){
cout<<"move "<<n<<" from "<<a<<" to "<<c<<endl;
flag = true;
}
count2++;
Towers(n-1,b,a,c, i);
}
}
Killed
這是我目前因為TLE修改的程式碼,但改了以後更後面的測資依然TLE:
#include
using namespace std;
int count2 = 0;
bool flag = false;
void Towers(int n,char a,char b,char c, int i);
int main() {
int n, i;
cin >> n >> i;
Towers(n,'1','2','3', i);
cout << "\n";
return 0;
}
void Towers(int n,char a,char b,char c, int i){
if(n==1){
if (flag == true){
return;
}
if (count2 == i-1){
cout<<"move "<
flag = true;
}
count2++;
}
else{
if (flag == true){
return;
}
Towers(n-1,a,c,b, i);
if (count2 == i-1){
cout<<"move "<
flag = true;
}
count2++;
Towers(n-1,b,a,c, i);
}
}
#12: 5% TLE (1s)
Killed
這題當然不能直接模擬,肯定TLE。
分析
第 i 次移動的規則:如果 i 在 前半部分 (2^(n-1)),則第 i 次移動來自搬動 n-1 個盤子的過程,也就是從 1=>2 先進行的步驟。
如果 i 剛好是 第 2^(n-1) 次移動,則我們搬動 n 號盤子。
否則,i 在 後半部分 (2^(n-1) + 1 之後),則它來自搬動 n-1 個盤子的第二段過程,這時 i 需要相對應地減去 2^(n-1),繼續計算剩餘的步驟。
完整程式:
#include <iostream>
#include <cstdio> // 提升輸出速度
using namespace std;
// 直接計算第 i 次移動是誰
void findMove(int n, long long i, char a, char b, char c) {
if (n == 1) {
printf("move 1 from %c to %c\n", a, c);
return;
}
long long half = (1LL << (n - 1)); // 2^(n-1)
if (i < half) {
findMove(n - 1, i, a, c, b); // i 在前半部分
} else if (i == half) {
printf("move %d from %c to %c\n", n, a, c); // 搬動最大的盤子
} else {
findMove(n - 1, i - half, b, a, c); // i 在後半部分
}
}
int main() {
int n;
long long i;
cin >> n >> i;
findMove(n, i, '1', '2', '3');
return 0;
}