fork download
  1. #include <vector>
  2. #include <iostream>
  3.  
  4. // 【】: 計算量
  5. // L : レーンの長さ
  6. // P : 多重度
  7. // S : すしの数
  8. // T : すしの時間合計
  9. // T ≦ PL
  10. //【P(L+S+PP)】
  11.  
  12. struct SUSHI {
  13. int pos;
  14. int time;
  15. };
  16.  
  17. struct LANE {
  18. std::vector < SUSHI > sushi;
  19. int length;
  20. };
  21.  
  22. struct LANE_INFO {
  23. std::vector < int > pile;
  24. int pile_max;
  25. std::vector < std::vector < int > > pos2sushi;
  26. };
  27.  
  28. // nをLで割った余り [0~L-1]
  29. int modulo(int n, int L){
  30. return n < 0 ? L - 1 - (- n - 1) % L : n % L;
  31. }
  32.  
  33. // a |= b
  34. void or_equal(std::vector < bool > &a, const std::vector < bool > &b){
  35. if (a.size() < b.size()){
  36. a.resize(b.size(), false);
  37. }
  38. for (int i = 0; i < b.size(); i++){
  39. a[i] = a[i] || b[i];
  40. }
  41. }
  42.  
  43. // (a & b) != 0
  44. bool intersect(const std::vector < bool > &a, const std::vector < bool > &b){
  45. for (int i = 0; i < a.size() && i < b.size(); i++){
  46. if (a[i] && b[i]){
  47. return true;
  48. }
  49. }
  50. return false;
  51. }
  52.  
  53. // 情報取得
  54. //【T】
  55. void get_lane_info(const LANE &lane, LANE_INFO &info){
  56. int L = lane.length;
  57.  
  58. // 多重度
  59. //【T】
  60. info.pile.clear();
  61. info.pile.resize(L, 0);
  62. for (int i = 0; i < lane.sushi.size(); i++){
  63. const SUSHI &sushi = lane.sushi[i];
  64. for (int j = 0; j < sushi.time; j++){
  65. info.pile[modulo(sushi.pos + j, L)] ++;
  66. }
  67. }
  68.  
  69. // 多重度最大値
  70. //【L】
  71. info.pile_max = 0;
  72. for (int i = 0; i < L; i++){
  73. if (info.pile[i] >= info.pile_max){
  74. info.pile_max = info.pile[i];
  75. }
  76. }
  77.  
  78. // レーン位置からSUSHIデータ情報へ
  79. //【S】
  80. info.pos2sushi.clear();
  81. info.pos2sushi.resize(L);
  82. for (int i = 0; i < lane.sushi.size(); i++){
  83. const SUSHI &sushi = lane.sushi[i];
  84. info.pos2sushi[sushi.pos].push_back(i);
  85. }
  86. }
  87.  
  88.  
  89. // オーバーラン量計算
  90. //【LP+SP+PPP】
  91. int get_overrun(const LANE &lane, int pos){
  92. int L = lane.length;
  93.  
  94. LANE_INFO info;
  95. get_lane_info(lane, info); //【T】
  96.  
  97. //【L】
  98. std::vector < int > over;
  99. for (int i = 0; i < lane.sushi.size(); i++){
  100. const SUSHI &sushi = lane.sushi[i];
  101. int n = modulo(pos - sushi.pos, L);
  102. if (0 < n && n < sushi.time){
  103. over.push_back(i);
  104. }
  105. }
  106.  
  107. //【P】
  108. std::vector < std::vector < bool > > connect(L, std::vector < bool >(over.size(), false));
  109. for (int i = 0 ; i < over.size() ; i++){
  110. const SUSHI &sushi = lane.sushi[over[i]];
  111. connect[sushi.pos][i] = true;
  112. connect[modulo(sushi.pos + sushi.time, L)][i] = true;
  113. }
  114.  
  115. //【LP+SP】
  116. for (int i = 0; i < L; i++){
  117. int p = modulo(pos + i, L);
  118. if (info.pile[p] < info.pile_max){
  119. or_equal(connect[modulo(p + 1, L)], connect[p]);
  120. }
  121. for (int j = 0; j < info.pos2sushi[p].size(); j++){
  122. const SUSHI &sushi = lane.sushi[info.pos2sushi[p][j]];
  123. or_equal(connect[modulo(p + sushi.time, L)], connect[p]);
  124. }
  125. }
  126.  
  127. //【PP】
  128. std::vector < std::vector < bool > > connect0;
  129. connect0.push_back(connect[pos]);
  130. for (int i = 0; i < over.size(); i++){
  131. connect0.push_back(connect[lane.sushi[over[i]].pos]);
  132. }
  133.  
  134. for (int i = 0; i < connect0.size(); i++){
  135. for (int j = i + 1; j < connect0.size(); j++){
  136. if (intersect(connect0[i], connect0[j])){
  137. or_equal(connect0[i], connect0[j]);
  138. if (j < connect0.size() - 1){
  139. connect0[j].swap(connect0.back());
  140. }
  141. connect0.pop_back();
  142. j = i;
  143. }
  144. }
  145. }
  146.  
  147. //【PP】
  148. int over_max = 0;
  149. for (int i = 1; i < connect0.size(); i++){
  150. int over_min = L;
  151. for (int j = 0; j < over.size(); j++){
  152. if (connect0[i][j]){
  153. const SUSHI &sushi = lane.sushi[over[j]];
  154. int o = modulo(sushi.pos + sushi.time - pos, L);
  155. if (o < over_min){
  156. over_min = o;
  157. }
  158. }
  159. }
  160. if (over_min > over_max){
  161. over_max = over_min;
  162. }
  163. }
  164. return over_max;
  165. }
  166.  
  167. // 最短時間計算
  168. //【LP+SP+PPP】
  169. int get_min_time(LANE lane, int start = 0, int time = 0){
  170. int L = lane.length;
  171. if (L == 0){
  172. return 0;
  173. }
  174.  
  175. // パラメーターの調整 ( 位置:[0~L-1], 長さ:[1~L]に )
  176. //【S】
  177. for (int i = 0; i < lane.sushi.size(); i++){
  178. SUSHI &sushi = lane.sushi[i];
  179.  
  180. int l = modulo(sushi.time-1, L) + 1;
  181. time -= l - sushi.time;
  182. sushi.time = l;
  183.  
  184. sushi.pos = modulo(sushi.pos, L);
  185. }
  186.  
  187. LANE_INFO info;
  188. get_lane_info(lane, info); //【T】
  189. if (info.pile_max == 0){
  190. return 0;
  191. }
  192.  
  193. // 多重度最大の先頭を調べる
  194. //【L】
  195. int pile_max_top = 0;
  196. for (int i = 0; i < L; i++){
  197. if (info.pile[modulo(start + i, L)] >= info.pile_max){
  198. pile_max_top = modulo(start + i + 1, L);
  199. }
  200. }
  201.  
  202. // 分解1
  203. int ov1 = get_overrun(lane, start); //【LP+SP+PPP】
  204. if (ov1 != 0 || pile_max_top == start){
  205. return info.pile_max * L + ov1 + time;
  206. }
  207.  
  208. // 分解2
  209. SUSHI dummy = { pile_max_top, modulo(start - pile_max_top, L) };
  210. lane.sushi.push_back(dummy);
  211. int ov2 = get_overrun(lane, pile_max_top); //【LP+SP+PPP】
  212. return (info.pile_max - 1) * L + modulo(pile_max_top - start, L) + ov2 + time;
  213. }
  214.  
  215. const char * const LANE_DATA[] = {
  216. "12_3",
  217. "313__",
  218. "4_35_1264_23_434",
  219. "123456789123456789",
  220. "88967472612377988186",
  221. "19898693316679441672",
  222. "93769682716711132249893",
  223. "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999",
  224. "123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789",
  225. NULL
  226. };
  227.  
  228. int main(){
  229. for (int i = 0 ; LANE_DATA[i] != NULL ; i++){
  230. LANE lane;
  231. int L = 0;
  232. for (int j = 0; ; j++){
  233. char ch = LANE_DATA[i][j];
  234. if (ch == '\0') {
  235. break;
  236. }
  237. if ('1' <= ch && ch <= '9'){
  238. SUSHI sushi = { j, ch - '0' };
  239. lane.sushi.push_back(sushi);
  240. }
  241. L++;
  242. }
  243. lane.length = L;
  244.  
  245. std::cout << "----------------------------------------------------------------\n";
  246. std::cout << LANE_DATA[i] << "\n";
  247. std::cout << "time : " << get_min_time(lane) << "\n";
  248. }
  249. return 0;
  250. }
  251.  
Success #stdin #stdout 0.01s 5424KB
stdin
Standard input is empty
stdout
----------------------------------------------------------------
12_3
time : 6
----------------------------------------------------------------
313__
time : 8
----------------------------------------------------------------
4_35_1264_23_434
time : 60
----------------------------------------------------------------
123456789123456789
time : 98
----------------------------------------------------------------
88967472612377988186
time : 149
----------------------------------------------------------------
19898693316679441672
time : 170
----------------------------------------------------------------
93769682716711132249893
time : 170
----------------------------------------------------------------
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
time : 2162
----------------------------------------------------------------
123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789
time : 1268