题解:CF1063E Lasers and Mirrors
用时:11 分 25 秒。
考虑到只要最优解法只要不是什么都不放,就会至少有一条光线出轨,故猜测答案是
容易发现可以在最后一行直接让一条光线出轨,然后这一列就变成空列了,我们可以把原来需要到这一列的光线引过来。反复这样做一定能在
一个小问题是这要求
/* 省选:2026.3.7 */
/* YMao99! */
/* Hatsune Miku x Kasane Teto */
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-(x)))
using namespace std;
const int N = 1010;
int n, a[N]; char ans[N][N];
int main()
{
#ifndef LOCAL
// freopen("cactus.in", "r", stdin);
// freopen("cactus.out", "w", stdout);
#endif
#ifdef LOCAL
// freopen("text.in", "r", stdin);
// freopen("prog.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; ++i) cin >> a[i];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
ans[i][j] = '.';
// 判断答案是否有可能是 n
bool flag = true;
for(int i = 1; i <= n; ++i) flag &= (i == a[i]);
if(flag)
{
cout << n << '\n';
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
cout << '.';
cout << '\n';
}
return 0;
}
// 记录每个点属于哪个环
vector < int > id(n + 1); int idx = 0;
for(int i = 1; i <= n; ++i)
{
if(!id[i])
{
++idx; int p = i;
while(!id[p]) id[p] = idx, p = a[p];
}
}
// 初始化
vector < bool > vis(n + 1); int last_pos = 0;
for(int i = 1; i <= n; ++i)
{
if(vis[id[i]]) continue;
a[last_pos] = a[i], a[i] = 0;
ans[n][i] = '\\'; vis[id[i]] = true;
last_pos = i;
}
// 构造
for(int i = n - 1; i >= 1; --i)
{
int ID = 0, pos = 0;
for(int j = 1; j <= n; ++j) if(a[j] == 0) ID = j;
for(int j = 1; j <= n; ++j) if(a[j] == ID) pos = j;
if(pos && ID)
{
if(pos < ID) ans[i][pos] = ans[i][ID] = '/';
else ans[i][pos] = ans[i][ID] = '\\';
a[ID] = ID, a[pos] = 0;
}
}
cout << n - 1 << '\n';
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
cout << ans[i][j];
cout << '\n';
}
return 0;
}
/*
*/