---
tags: IOI
---
# IOI2008 Day1-1 活字印刷機 (Type Printer)
なんでIOIに難易度6があるんだ :thinking_face:
## 問題
https://www.ioi-jp.org/ioi/2008/problems/Day1_jpn/type_printer_j.pdf
https://oj.uz/problem/view/IOI08_printer
あなたは $N$ 個の単語を好きな順番で印刷したいです。
あなたは活字印刷機に対して以下の操作ができます。
- 印刷機の現在の単語の最後に 1 文字を追加する
- 印刷機の現在の単語の最後の 1 文字を削除する
- 印刷機の現在の単語を印刷する
最小の操作回数と、そのときの操作を答えてください。
## 考察
最後に印刷機の単語を空にするとして考えると、 prefix が同じものをできるだけ隣あわせにするとよく、これはソートすると最適になりそう。
そこから、最後の印刷機の単語の分操作回数が減るので、最後が最長になるように文字を入れ替えてからソートすると良い。
## 実装
https://oj.uz/submission/217174
```cpp
#include <bits/stdc++.h>
using namespace std;
#define name3(a,b,c,d,...) d
#define rep1(a) for(int i = 0; i < a; i++)
#define rep2(i,a) for(int i = 0; i < a; i++)
#define rep3(i,a,b) for(int i = a; i < b; i++)
#define rep(...) name3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define each(i,a) for(auto&& i : a)
#define all(a) begin(a), end(a)
int main(){
cin.tie(nullptr);
ios::sync_with_stdio(false);
int n;
cin >> n;
vector<string> a(n);
string t;
each(i, a){
cin >> i;
if(t.size() < i.size()) t = i;
}
each(i, a) rep(j, i.size()) i[j] ^= t[j] ^ -1;
sort(all(a));
each(i, a) rep(j, i.size()) i[j] ^= t[j] ^ -1;
string ans;
ans += a[0];
ans += 'P';
rep(n - 1){
int at = 0;
while(at < a[i].size() && at < a[i + 1].size() && a[i][at] == a[i + 1][at]) at++;
rep(j, at, a[i].size()) ans += '-';
rep(j, at, a[i + 1].size()) ans += a[i + 1][j];
ans += 'P';
}
cout << ans.size() << '\n';
each(i, ans) cout << i << '\n';
}
```