CodeChef is a non-commercial competitive programming community
Login
Username (New User? Signup) Password (Forgot Password?)
Signup
Login or
Signup with
Connect
Note
  • Publicize your achievements on your Facebook Wall.
  • Challenge your friends or ask them for help.

Site Navigation

  • PRACTICE
    • Easy
    • Medium
    • Hard
    • Challenge
    • Peer
  • COMPETE
    • February CookOff
    • February Long Contest
    • January CookOff
  • DISCUSS
    • Wiki
    • Forums
    • Blog
    • Twitter
  • COMMUNITY
    • CodeChef Meetups
    • Campus Chapters
    • Host your Contest
    • User Groups
    • CodeChef TechTalks
    • All Educational Initiatives
    • Event Calendar
  • HELP
    • Frequently Asked Questions
    • FAQ for problem setters
    • Problem Setting
    • Ranks
    • Tutorials
  • ABOUT
    • About CodeChef
    • Team CodeChef
    • Press Room
    • CodeChef Financials
    • CodeChef Sponsorships
    • CEO's Corner
    • Contact Us
    • About Directi
Home  » November 2009 (Contest X) » Help the DJ » All Submissions » Mark Greve [131092]
0
Your rating: None

CodeChef submission 131092 (C++ 4.0.0-8)

CodeChef submission 131092 (C++ 4.0.0-8) plaintext list. Status: TLE, problem JX, contest NOV09. By gmark (Mark Greve), 2009-11-11 14:59:23.
  1. // Help the DJ
  2. // Source: CodeChef November Algorithm Challenge
  3. // CodeChef ID:
  4. // Author: Mark Greve
  5.  
  6. #define LOCAL
  7. #ifdef LOCAL
  8. #include <dirent.h>
  9. #include <fstream>
  10. #endif
  11.  
  12. #include <algorithm>
  13. #include <bitset>
  14. #include <cassert>
  15. #include <cctype>
  16. #include <cmath>
  17. #include <cstdio>
  18. #include <cstdlib>
  19. #include <cstring>
  20. #include <ctime>
  21. #include <deque>
  22. #include <functional>
  23. #include <iomanip>
  24. #include <iostream>
  25. #include <list>
  26. #include <map>
  27. #include <numeric>
  28. #include <queue>
  29. #include <set>
  30. #include <sstream>
  31. #include <stack>
  32. #include <string>
  33. #include <utility>
  34. #include <vector>
  35. using namespace std;
  36.  
  37. typedef vector<vector<int> > vvi;
  38.  
  39. // Global variables to store the current best answer
  40. vector<int> REAL_ANS;
  41. int BEST_SOL;
  42.  
  43. inline int sqr(int x) { return x*x; }
  44.  
  45. // FAST IO
  46. //{{{
  47. // FAST IO
  48. char *start;
  49. const int MAXBUF=40000000;
  50. char buf[MAXBUF];
  51. int bufsz;
  52. void take_input() {
  53. bufsz=fread(buf, sizeof(char), MAXBUF-1, stdin);
  54. buf[bufsz]='\0';
  55. start=buf;
  56. }
  57. void skip() { while (*start != '.' && !isdigit(*start)) ++start; }
  58. void GETNUM(int& n){
  59. skip();
  60. n=0;
  61. while (isdigit(*start)) n = n*10 + *start-'0', ++start;
  62. }
  63. // END FAST IO
  64. //}}}
  65.  
  66. // Evaluating a solution
  67. //{{{
  68. int eval_solution(const vvi& v, const vector<int>& sol) {
  69. if (sol.empty()) {
  70. return 0;
  71. }
  72.  
  73. int ndancers = v.size()-1;
  74. int nsongs = v[0].size()-1;
  75.  
  76. vector<bool> covered(ndancers,0);
  77. vector<int> bored(ndancers);
  78. for (int i=0;i<ndancers;++i) bored[i] = v[i][nsongs];
  79.  
  80. int ans = 0;
  81. for (int i=0;i<sol.size();++i) {
  82. int cursong = sol[i];
  83. for (int j=0;j<ndancers;++j) {
  84. if (v[j][cursong]) {
  85. if (!covered[j] && bored[j]>0) {
  86. covered[j] = 1;
  87. ++ans;
  88. }
  89. }
  90. else {
  91. --bored[j];
  92. if (covered[j] && bored[j]==0) {
  93. --ans;
  94. }
  95. }
  96. }
  97. }
  98. return ans;
  99. }
  100. //}}}
  101.  
  102. // GREEDY WITH BACKTRACKING
  103. //{{{
  104. const int GMAX=501;
  105. int G_bored[GMAX];
  106. int G_ans;
  107. int G_covered[GMAX];
  108. int G_ndancers;
  109. int G_nsongs;
  110. int G_selected[GMAX];
  111. int G_MAXITS;
  112. int G_countones[GMAX];
  113. int G_outbored;
  114. int G_contained_in[GMAX];
  115. bool G_chosen[GMAX];
  116.  
  117. void setup_greedy_backtracking(const vvi& v, int iterations) {
  118. G_MAXITS = iterations;
  119. G_ndancers = v.size()-1;
  120. G_nsongs = v[0].size()-1;
  121. G_outbored = 0;
  122.  
  123. if (BEST_SOL == G_ndancers) {
  124. G_MAXITS=0;
  125. return;
  126. }
  127.  
  128. for (int i=0;i<G_nsongs;++i) {
  129. G_chosen[i] = 0;
  130. }
  131.  
  132. for (int i=0;i<G_ndancers;++i) {
  133. G_bored[i] = v[i][G_nsongs];
  134. G_covered[i] = 0;
  135. G_contained_in[i] = 0;
  136. }
  137.  
  138. for (int j=0;j<G_ndancers;++j) {
  139. for (int i=0;i<G_nsongs;++i) {
  140. if (v[j][i]) {
  141. ++G_contained_in[j];
  142. }
  143. }
  144. }
  145.  
  146. G_ans = 0;
  147. }
  148. void greedy_with_backtracking2(const vvi& v, int at) {
  149. if (G_ans > BEST_SOL) { // Update to a better solution
  150. BEST_SOL = G_ans;
  151. REAL_ANS.clear();
  152. for (int i=0;i<at;++i) {
  153. REAL_ANS.push_back(G_selected[i]);
  154. }
  155. if (BEST_SOL == G_ndancers) {
  156. G_MAXITS = 0;
  157. return;
  158. }
  159. }
  160.  
  161. if (G_ndancers - G_outbored <= BEST_SOL) return;
  162. //printf("AT: %d, G_ANS %d G_OUT %d G_NDAN %d BEST %d\n", at, G_ans, G_outbored, G_ndancers, BEST_SOL);
  163.  
  164. --G_MAXITS;
  165. if (G_MAXITS <= 0) return;
  166.  
  167. set<pair<int,int > > scores;
  168. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  169. int num = 0;
  170. for (int j=0;j<G_ndancers;++j) {
  171. if (v[j][z]) {
  172. if (!G_covered[j] && G_bored[j]>0) {
  173. num += 10000 + sqr(G_nsongs+1-G_contained_in[j]);
  174. }
  175. else if (G_covered[j] && G_bored[j]>0) {
  176. num += 20;
  177. }
  178. }
  179. else {
  180. if (G_covered[j] && G_bored[j]==1) {
  181. num -= 10000;
  182. }
  183. }
  184. }
  185. if (num > 0) {
  186. scores.insert(make_pair(-num,z));
  187. while (scores.size()>4) {
  188. scores.erase(--scores.end());
  189. }
  190. }
  191. }
  192.  
  193. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  194. int z = it->second;
  195. int prev_ans = G_ans;
  196. for (int j=0;j<G_ndancers;++j) {
  197. if (v[j][z]) {
  198. ++G_covered[j];
  199. --G_contained_in[j];
  200. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  201. }
  202. else {
  203. if (G_bored[j]==1) {
  204. if (G_covered[j]) {
  205. --G_ans;
  206. }
  207. ++G_outbored;
  208. }
  209. --G_bored[j];
  210. }
  211. }
  212.  
  213. if (G_ans>prev_ans) {
  214. G_chosen[z] = 1;
  215. G_selected[at] = z;
  216. greedy_with_backtracking2(v, at+1);
  217. G_chosen[z] = 0;
  218. }
  219.  
  220. for (int j=0;j<G_ndancers;++j) {
  221. if (v[j][z]) {
  222. --G_covered[j];
  223. ++G_contained_in[j];
  224. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  225. }
  226. else {
  227. ++G_bored[j];
  228. if (G_bored[j]==1) {
  229. if (G_covered[j]) ++G_ans;
  230. --G_outbored;
  231. }
  232. }
  233. }
  234. }
  235. }
  236. void greedy_with_backtracking3(const vvi& v, int at) {
  237. if (G_ans > BEST_SOL) { // Update to a better solution
  238. BEST_SOL = G_ans;
  239. REAL_ANS.clear();
  240. for (int i=0;i<at;++i) {
  241. REAL_ANS.push_back(G_selected[i]);
  242. }
  243. if (BEST_SOL == G_ndancers) {
  244. G_MAXITS = 0;
  245. return;
  246. }
  247. }
  248.  
  249. if (G_ndancers - G_outbored <= BEST_SOL) return;
  250.  
  251. --G_MAXITS;
  252. if (G_MAXITS <= 0) return;
  253.  
  254. set<pair<int,int > > scores;
  255. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  256. int num = 0;
  257. for (int j=0;j<G_ndancers;++j) {
  258. if (v[j][z]) {
  259. if (!G_covered[j] && G_bored[j]>0) {
  260. num += 1000000 + 40*(G_nsongs+1-G_contained_in[j]) + 41*sqr(G_nsongs - G_bored[j]);
  261. }
  262. else if (G_covered[j] && G_bored[j]>0) {
  263. num += 20;
  264. }
  265. }
  266. else {
  267. if (G_covered[j] && G_bored[j]==1) {
  268. num -= 1000000;
  269. }
  270. }
  271. }
  272. if (num > 0) {
  273. scores.insert(make_pair(-num,z));
  274. while (scores.size()>4) {
  275. scores.erase(--scores.end());
  276. }
  277. }
  278. }
  279.  
  280. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  281. int z = it->second;
  282. int prev_ans = G_ans;
  283. for (int j=0;j<G_ndancers;++j) {
  284. if (v[j][z]) {
  285. ++G_covered[j];
  286. --G_contained_in[j];
  287. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  288. }
  289. else {
  290. if (G_bored[j]==1) {
  291. if (G_covered[j]) {
  292. --G_ans;
  293. }
  294. ++G_outbored;
  295. }
  296. --G_bored[j];
  297. }
  298. }
  299.  
  300. if (G_ans>prev_ans) {
  301. G_chosen[z] = 1;
  302. G_selected[at] = z;
  303. greedy_with_backtracking3(v, at+1);
  304. G_chosen[z] = 0;
  305. }
  306.  
  307. for (int j=0;j<G_ndancers;++j) {
  308. if (v[j][z]) {
  309. --G_covered[j];
  310. ++G_contained_in[j];
  311. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  312. }
  313. else {
  314. ++G_bored[j];
  315. if (G_bored[j]==1) {
  316. if (G_covered[j]) ++G_ans;
  317. --G_outbored;
  318. }
  319. }
  320. }
  321. }
  322. }
  323. void greedy_with_backtracking4(const vvi& v, int at) {
  324. if (G_ans > BEST_SOL) { // Update to a better solution
  325. //assert(0);
  326. BEST_SOL = G_ans;
  327. REAL_ANS.clear();
  328. for (int i=0;i<at;++i) {
  329. REAL_ANS.push_back(G_selected[i]);
  330. }
  331. if (BEST_SOL == G_ndancers) {
  332. G_MAXITS = 0;
  333. return;
  334. }
  335. }
  336.  
  337. if (G_ndancers - G_outbored <= BEST_SOL) return;
  338.  
  339. --G_MAXITS;
  340. if (G_MAXITS <= 0) return;
  341.  
  342. set<pair<int,int > > scores;
  343. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  344. int num = 0;
  345. for (int j=0;j<G_ndancers;++j) {
  346. if (v[j][z]) {
  347. if (G_bored[j]>0) {
  348. if (!G_covered[j]) {
  349. if (G_bored[j]<=3) num += 100000;
  350. else num += 10;
  351. }
  352. else {
  353. if (G_bored[j]<=3) num += 10000;
  354. else ++num;
  355. }
  356. }
  357. }
  358. else {
  359. if (G_bored[j]==1) {
  360. if (G_covered[j]) num -= 100000;
  361. else num -= 100000;
  362. }
  363. else if (G_bored[j]==2) num -= 10000;
  364. else if (G_bored[j]==3) num -= 1000;
  365. }
  366. }
  367. if (num > 0) {
  368. scores.insert(make_pair(-num,z));
  369. while (scores.size()>10) {
  370. scores.erase(--scores.end());
  371. }
  372. }
  373. }
  374.  
  375. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  376. int z = it->second;
  377. int prev_ans = G_ans;
  378. for (int j=0;j<G_ndancers;++j) {
  379. if (v[j][z]) {
  380. ++G_covered[j];
  381. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  382. }
  383. else {
  384. if (G_bored[j]==1) {
  385. if (G_covered[j]) {
  386. --G_ans;
  387. }
  388. ++G_outbored;
  389. }
  390. --G_bored[j];
  391. }
  392. }
  393.  
  394. if (G_ans>prev_ans) {
  395. G_chosen[z] = 1;
  396. G_selected[at] = z;
  397. greedy_with_backtracking4(v, at+1);
  398. G_chosen[z] = 0;
  399. }
  400.  
  401. for (int j=0;j<G_ndancers;++j) {
  402. if (v[j][z]) {
  403. --G_covered[j];
  404. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  405. }
  406. else {
  407. ++G_bored[j];
  408. if (G_bored[j]==1) {
  409. if (G_covered[j]) ++G_ans;
  410. --G_outbored;
  411. }
  412. }
  413. }
  414. }
  415. }
  416. void greedy_with_backtracking5(const vvi& v, int at) {
  417. if (G_ans > BEST_SOL) { // Update to a better solution
  418. //cerr << " GR 5 UPDATE TO " << G_ans << " vs " << BEST_SOL << endl;
  419. BEST_SOL = G_ans;
  420. REAL_ANS.clear();
  421. for (int i=0;i<at;++i) {
  422. REAL_ANS.push_back(G_selected[i]);
  423. }
  424. if (BEST_SOL == G_ndancers) {
  425. G_MAXITS = 0;
  426. return;
  427. }
  428. }
  429.  
  430. if (at>=25) return;
  431. if (G_ndancers - G_outbored <= BEST_SOL) return;
  432.  
  433. --G_MAXITS;
  434. if (G_MAXITS <= 0) return;
  435.  
  436. set<pair<int,int > > scores;
  437. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  438. int num = 0;
  439. for (int j=0;j<G_ndancers;++j) {
  440. if (v[j][z]) {
  441. if (!G_covered[j]) num += 40*(G_nsongs+1-G_contained_in[j]);
  442. }
  443. else {
  444. if (G_bored[j]==1) {
  445. if (G_covered[j]) num -= 40*G_nsongs;
  446. else num -= 20*G_nsongs;
  447. }
  448. }
  449. }
  450. if (num > 0) {
  451. scores.insert(make_pair(-num,z));
  452. while (scores.size()>7) { scores.erase(--scores.end()); }
  453. }
  454. }
  455.  
  456. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  457. int z = it->second;
  458. int prev_ans = G_ans;
  459. for (int j=0;j<G_ndancers;++j) {
  460. if (v[j][z]) {
  461. --G_contained_in[j];
  462. ++G_covered[j];
  463. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  464. }
  465. else {
  466. if (G_bored[j]==1) {
  467. if (G_covered[j]) {
  468. --G_ans;
  469. }
  470. ++G_outbored;
  471. }
  472. --G_bored[j];
  473. }
  474. }
  475.  
  476. if (G_ans>prev_ans) {
  477. G_chosen[z] = 1;
  478. G_selected[at] = z;
  479. greedy_with_backtracking5(v, at+1);
  480. G_chosen[z] = 0;
  481. }
  482.  
  483. for (int j=0;j<G_ndancers;++j) {
  484. if (v[j][z]) {
  485. ++G_contained_in[j];
  486. --G_covered[j];
  487. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  488. }
  489. else {
  490. ++G_bored[j];
  491. if (G_bored[j]==1) {
  492. if (G_covered[j]) ++G_ans;
  493. --G_outbored;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. void greedy_with_backtracking6(const vvi& v, int at) {
  500. //printf("G_ANS: %d, AT: %d, OUT: %d\n", G_ans,at, G_outbored);
  501. if (G_ans > BEST_SOL) { // Update to a better solution
  502. //cerr << "GR 6 UP TO " << G_ans << " prev " << BEST_SOL << endl;
  503. //assert(0);
  504. BEST_SOL = G_ans;
  505. REAL_ANS.clear();
  506. for (int i=0;i<at;++i) {
  507. REAL_ANS.push_back(G_selected[i]);
  508. }
  509. if (BEST_SOL == G_ndancers) {
  510. G_MAXITS = 0;
  511. return;
  512. }
  513. }
  514.  
  515. if (at>=25) { return; }
  516. if (G_ndancers - G_outbored <= BEST_SOL) return;
  517.  
  518. --G_MAXITS;
  519. if (G_MAXITS <= 0) return;
  520.  
  521. set<pair<int,int > > scores;
  522. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  523. int num = 0;
  524. for (int j=0;j<G_ndancers;++j) {
  525. if (v[j][z]) {
  526. if (!G_covered[j]) num += 100000;
  527. num += 40*sqr(G_nsongs+1-G_bored[j]);
  528. }
  529. else {
  530. if (G_bored[j]==1) {
  531. if (G_covered[j]) num -= 100000;
  532. num -= 20*G_nsongs;
  533. }
  534. }
  535. }
  536. if (num > 0) {
  537. scores.insert(make_pair(-num,z));
  538. while (scores.size()>4) { scores.erase(--scores.end()); }
  539. }
  540. }
  541.  
  542. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  543. int z = it->second;
  544. int prev_ans = G_ans;
  545. for (int j=0;j<G_ndancers;++j) {
  546. if (v[j][z]) {
  547. ++G_covered[j];
  548. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  549. }
  550. else {
  551. if (G_bored[j]==1) {
  552. if (G_covered[j]) {
  553. --G_ans;
  554. }
  555. ++G_outbored;
  556. }
  557. --G_bored[j];
  558. }
  559. }
  560.  
  561. if (G_ans>prev_ans) {
  562. G_chosen[z] = 1;
  563. G_selected[at] = z;
  564. greedy_with_backtracking6(v, at+1);
  565. G_chosen[z] = 0;
  566. }
  567.  
  568. for (int j=0;j<G_ndancers;++j) {
  569. if (v[j][z]) {
  570. --G_covered[j];
  571. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  572. }
  573. else {
  574. ++G_bored[j];
  575. if (G_bored[j]==1) {
  576. if (G_covered[j]) ++G_ans;
  577. --G_outbored;
  578. }
  579. }
  580. }
  581. }
  582. }
  583. void greedy_with_backtracking7(const vvi& v, int at) {
  584. if (G_ans > BEST_SOL) { // Update to a better solution
  585. //assert(0);
  586. BEST_SOL = G_ans;
  587. REAL_ANS.clear();
  588. for (int i=0;i<at;++i) {
  589. REAL_ANS.push_back(G_selected[i]);
  590. }
  591. if (BEST_SOL == G_ndancers) {
  592. G_MAXITS = 0;
  593. return;
  594. }
  595. }
  596.  
  597. if (at>=25) {
  598. return;
  599. }
  600. if (G_ndancers - G_outbored <= BEST_SOL) return;
  601.  
  602. --G_MAXITS;
  603. if (G_MAXITS <= 0) return;
  604.  
  605. set<pair<int,int > > scores;
  606. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  607. int num = 0;
  608. for (int j=0;j<G_ndancers;++j) {
  609. if (v[j][z]) {
  610. if (G_bored[j]>0) {
  611. if (!G_covered[j]) {
  612. if (G_bored[j]<=3) num += 100000;
  613. else num += 10;
  614. }
  615. else {
  616. if (G_bored[j]<=3) num += 10000;
  617. else ++num;
  618. }
  619. }
  620. }
  621. else {
  622. if (G_bored[j]==1) {
  623. if (G_covered[j]) num -= 100000;
  624. else num -= 100000;
  625. }
  626. else if (G_bored[j]==2) num -= 10000;
  627. else if (G_bored[j]==3) num -= 1000;
  628. }
  629. }
  630. if (num > 0) {
  631. scores.insert(make_pair(-num,z));
  632. while (scores.size()>4) {
  633. scores.erase(--scores.end());
  634. }
  635. }
  636. }
  637.  
  638. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  639. int z = it->second;
  640. int prev_ans = G_ans;
  641. for (int j=0;j<G_ndancers;++j) {
  642. if (v[j][z]) {
  643. ++G_covered[j];
  644. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  645. }
  646. else {
  647. if (G_bored[j]==1) {
  648. if (G_covered[j]) {
  649. --G_ans;
  650. }
  651. ++G_outbored;
  652. }
  653. --G_bored[j];
  654. }
  655. }
  656.  
  657. if (G_ans>prev_ans) {
  658. G_chosen[z] = 1;
  659. G_selected[at] = z;
  660. greedy_with_backtracking7(v, at+1);
  661. G_chosen[z] = 0;
  662. }
  663.  
  664. for (int j=0;j<G_ndancers;++j) {
  665. if (v[j][z]) {
  666. --G_covered[j];
  667. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  668. }
  669. else {
  670. ++G_bored[j];
  671. if (G_bored[j]==1) {
  672. if (G_covered[j]) ++G_ans;
  673. --G_outbored;
  674. }
  675. }
  676. }
  677. }
  678. }
  679. void greedy_with_backtracking8(const vvi& v, int at) {
  680. if (G_ans > BEST_SOL) { // Update to a better solution
  681. //cerr << "\tGREEDYBT 8: IMPROVE " << G_ans << endl;
  682. BEST_SOL = G_ans;
  683. REAL_ANS.clear();
  684. for (int i=0;i<at;++i) {
  685. REAL_ANS.push_back(G_selected[i]);
  686. }
  687. if (BEST_SOL == G_ndancers) {
  688. G_MAXITS = 0;
  689. return;
  690. }
  691. }
  692.  
  693. if (at>=25) {
  694. return;
  695. }
  696. if (G_ndancers - G_outbored <= BEST_SOL) return;
  697.  
  698. --G_MAXITS;
  699. if (G_MAXITS <= 0) return;
  700.  
  701. set<pair<int,int > > scores;
  702. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  703. int num = 0;
  704. for (int j=0;j<G_ndancers;++j) {
  705. if (v[j][z]) {
  706. if (G_bored[j]>0) {
  707. if (!G_covered[j]) {
  708. if (G_bored[j]<=5) num += 100000;
  709. else num += 10;
  710. }
  711. else {
  712. if (G_bored[j]<=5) num += 10000;
  713. else ++num;
  714. }
  715. }
  716. }
  717. else {
  718. if (G_bored[j]==1) {
  719. num -= 100000;
  720. }
  721. else if (G_bored[j]==2) num -= 10000;
  722. else if (G_bored[j]==3) num -= 1000;
  723. }
  724. }
  725. if (num > 0) {
  726. scores.insert(make_pair(-num,z));
  727. while (scores.size()>10) {
  728. scores.erase(--scores.end());
  729. }
  730. }
  731. }
  732.  
  733. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  734. int z = it->second;
  735. int prev_ans = G_ans;
  736. for (int j=0;j<G_ndancers;++j) {
  737. if (v[j][z]) {
  738. ++G_covered[j];
  739. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  740. }
  741. else {
  742. if (G_bored[j]==1) {
  743. if (G_covered[j]) {
  744. --G_ans;
  745. }
  746. ++G_outbored;
  747. }
  748. --G_bored[j];
  749. }
  750. }
  751.  
  752. if (G_ans>prev_ans) {
  753. G_chosen[z] = 1;
  754. G_selected[at] = z;
  755. greedy_with_backtracking8(v, at+1);
  756. G_chosen[z] = 0;
  757. }
  758.  
  759. for (int j=0;j<G_ndancers;++j) {
  760. if (v[j][z]) {
  761. --G_covered[j];
  762. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  763. }
  764. else {
  765. ++G_bored[j];
  766. if (G_bored[j]==1) {
  767. if (G_covered[j]) ++G_ans;
  768. --G_outbored;
  769. }
  770. }
  771. }
  772. }
  773. }
  774.  
  775. inline int score(const vvi& v, int z) {
  776. const int NDANCERS = v.size()-1;
  777. int num = 0;
  778. for (int j=0;j<NDANCERS;++j) {
  779. if (v[j][z]) {
  780. if (G_bored[j]>0) {
  781. if (!G_covered[j]) {
  782. if (G_bored[j]<=4) num += 100000;
  783. else num += 100000/5;
  784. }
  785. else {
  786. if (G_bored[j]<=4) num += 10000;
  787. else ++num;
  788. }
  789. }
  790. }
  791. else {
  792. if (G_bored[j]>0) {
  793. if (G_covered[j]) {
  794. if (G_bored[j]==1 || G_contained_in[j]==1) num -= 100000;
  795. else if (G_bored[j]==2 || G_contained_in[j]==2) num -= 2000;
  796. else if (G_bored[j]==3 || G_contained_in[j]==3) num -= 300;
  797. }
  798. }
  799. }
  800. }
  801. return num;
  802. }
  803. void greedy_with_backtracking10(const vvi& v, int at) {
  804. if (G_ans > BEST_SOL) { // Update to a better solution
  805. BEST_SOL = G_ans;
  806. REAL_ANS.clear();
  807. for (int i=0;i<at;++i) {
  808. REAL_ANS.push_back(G_selected[i]);
  809. }
  810. if (BEST_SOL == G_ndancers) {
  811. G_MAXITS = 0;
  812. return;
  813. }
  814. }
  815.  
  816. if (at>=10) return;
  817. if (G_ndancers - G_outbored <= BEST_SOL) return;
  818. //printf("AT: %d, G_ANS %d G_OUT %d G_NDAN %d BEST %d\n", at, G_ans, G_outbored, G_ndancers, BEST_SOL);
  819.  
  820. --G_MAXITS;
  821. if (G_MAXITS <= 0) return;
  822.  
  823. set<pair<int,int > > scores;
  824. for (int z=0;z<G_nsongs && G_MAXITS > 0;++z) if (!G_chosen[z]) {
  825. int num = score(v,z);
  826. if (num > 0) {
  827. scores.insert(make_pair(-num,z));
  828. while (scores.size()>6) {
  829. scores.erase(--scores.end());
  830. }
  831. }
  832. }
  833.  
  834. for (set<pair<int,int> >::iterator it = scores.begin(); it != scores.end(); ++it) {
  835. int z = it->second;
  836. int prev_ans = G_ans;
  837. for (int j=0;j<G_ndancers;++j) {
  838. if (v[j][z]) {
  839. ++G_covered[j];
  840. --G_contained_in[j];
  841. if (G_covered[j]==1 && G_bored[j]>0) ++G_ans;
  842. }
  843. else {
  844. if (G_bored[j]==1) {
  845. if (G_covered[j]) {
  846. --G_ans;
  847. }
  848. ++G_outbored;
  849. }
  850. --G_bored[j];
  851. }
  852. }
  853.  
  854. if (G_ans>prev_ans) {
  855. G_chosen[z] = 1;
  856. G_selected[at] = z;
  857. greedy_with_backtracking10(v, at+1);
  858. G_chosen[z] = 0;
  859. }
  860.  
  861. for (int j=0;j<G_ndancers;++j) {
  862. if (v[j][z]) {
  863. ++G_contained_in[j];
  864. --G_covered[j];
  865. if (G_covered[j]==0 && G_bored[j]>0) --G_ans;
  866. }
  867. else {
  868. ++G_bored[j];
  869. if (G_bored[j]==1) {
  870. if (G_covered[j]) ++G_ans;
  871. --G_outbored;
  872. }
  873. }
  874. }
  875. }
  876. }
  877. //}}}
  878. // END GREEDY WITH BACKTRACKING
  879.  
  880. // GREEDY SET COVER SOLUTION
  881. //{{{
  882. void greedy(const vvi& v) {
  883. if (BEST_SOL == v.size()-1)
  884. return;
  885.  
  886. int ndancers = v.size()-1;
  887. int nsongs = v[0].size()-1;
  888.  
  889. vector<int> contained_in(ndancers,0);
  890. for (int j=0;j<ndancers;++j) {
  891. for (int i=0;i<nsongs;++i) {
  892. if (v[j][i]) {
  893. ++contained_in[j];
  894. }
  895. }
  896. }
  897.  
  898. vector<int> bored(ndancers);
  899. for (int i=0;i<ndancers;++i) {
  900. bored[i] = v[i][nsongs];
  901. }
  902.  
  903. vector<int> choices;
  904. vector<int> covered(ndancers,0);
  905. vector<bool> chosen(nsongs,0);
  906.  
  907. int curans = 0;
  908. int bestprefix = 0;
  909. int bestans = 0;
  910.  
  911. while (1) {
  912. int choice = -1, best = 0;
  913. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  914. int num = 0;
  915. for (int j=0;j<ndancers;++j) {
  916. if (v[j][i]) {
  917. if (!covered[j] && bored[j]>0) {
  918. //++num;
  919. num += /*v[j][nsongs]*/ + 10000 + (nsongs-contained_in[j]);
  920. }
  921. else if (covered[j] && bored[j]>0) {
  922. //num += 20;
  923. }
  924. }
  925. else {
  926. if (covered[j] && bored[j]==1) {
  927. //--num;
  928. num -= 10000;
  929. }
  930. }
  931. }
  932.  
  933. if (num > best || (num>=best && (rand()&1))) {
  934. choice = i;
  935. best = num;
  936. }
  937. }
  938. if (choice==-1) break;
  939.  
  940. // Update for each dancer whether covered or not (and the boredom)
  941. for (int j=0;j<ndancers;++j) {
  942. if (v[j][choice]) {
  943. ++covered[j];
  944. if (covered[j] == 1 && bored[j]>0) {
  945. ++curans;
  946. }
  947. }
  948. else {
  949. --bored[j];
  950. if (bored[j]==0 && covered[j]) {
  951. --curans;
  952. }
  953. }
  954. }
  955.  
  956. chosen[choice] = 1;
  957. choices.push_back(choice);
  958.  
  959. if (curans > bestans) {
  960. bestans = curans;
  961. bestprefix = choices.size();
  962. }
  963. }
  964.  
  965. if (bestans > BEST_SOL) {
  966. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  967. BEST_SOL = bestans;
  968. }
  969. }
  970. //}}}
  971. // END GREEDY
  972.  
  973. // GREEDY SET COVER SOLUTION 2
  974. //{{{
  975. void greedy2(const vvi& v) {
  976. if (BEST_SOL == v.size()-1)
  977. return;
  978.  
  979. int ndancers = v.size()-1;
  980. int nsongs = v[0].size()-1;
  981.  
  982. vector<int> contained_in(ndancers,0);
  983. for (int j=0;j<ndancers;++j) {
  984. for (int i=0;i<nsongs;++i) {
  985. if (v[j][i]) {
  986. ++contained_in[j];
  987. }
  988. }
  989. }
  990.  
  991. vector<int> bored(ndancers);
  992. for (int i=0;i<ndancers;++i) {
  993. bored[i] = v[i][nsongs];
  994. }
  995.  
  996. vector<int> choices;
  997. vector<int> covered(ndancers,0);
  998. vector<bool> chosen(nsongs,0);
  999.  
  1000. int curans = 0;
  1001. int bestprefix = 0;
  1002. int bestans = 0;
  1003.  
  1004. while (1) {
  1005. int choice = -1, best = 0;
  1006. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1007. int num = 0;
  1008. for (int j=0;j<ndancers;++j) {
  1009. if (v[j][i]) {
  1010. if (!covered[j] && bored[j]>0) {
  1011. num += v[j][nsongs] + 10000;
  1012. }
  1013. else if (covered[j] && bored[j]>0) {
  1014. num += 20;
  1015. }
  1016. }
  1017. else {
  1018. if (covered[j] && bored[j]==1) {
  1019. num -= 10000;
  1020. }
  1021. }
  1022. }
  1023.  
  1024. if (num > best || (num>=best && (rand()&1))) {
  1025. choice = i;
  1026. best = num;
  1027. }
  1028. }
  1029. if (choice==-1) break;
  1030.  
  1031. // Update for each dancer whether covered or not (and the boredom)
  1032. for (int j=0;j<ndancers;++j) {
  1033. if (v[j][choice]) {
  1034. ++covered[j];
  1035. if (covered[j] == 1 && bored[j]>0) {
  1036. ++curans;
  1037. }
  1038. }
  1039. else {
  1040. --bored[j];
  1041. if (bored[j]==0 && covered[j]) {
  1042. --curans;
  1043. }
  1044. }
  1045. }
  1046.  
  1047. chosen[choice] = 1;
  1048. choices.push_back(choice);
  1049.  
  1050. if (curans > bestans) {
  1051. bestans = curans;
  1052. bestprefix = choices.size();
  1053. }
  1054. }
  1055. if (bestans > BEST_SOL) {
  1056. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1057. BEST_SOL = bestans;
  1058. }
  1059. }
  1060. //}}}
  1061. // END GREEDY 2
  1062.  
  1063. // GREEDY SET COVER SOLUTION 3
  1064. //{{{
  1065. void greedy3(const vvi& v) {
  1066. if (BEST_SOL == v.size()-1)
  1067. return;
  1068.  
  1069. int ndancers = v.size()-1;
  1070. int nsongs = v[0].size()-1;
  1071.  
  1072. vector<int> contained_in(ndancers,0);
  1073. for (int j=0;j<ndancers;++j) {
  1074. for (int i=0;i<nsongs;++i) {
  1075. if (v[j][i]) {
  1076. ++contained_in[j];
  1077. }
  1078. }
  1079. }
  1080.  
  1081. vector<int> bored(ndancers);
  1082. for (int i=0;i<ndancers;++i) {
  1083. bored[i] = v[i][nsongs];
  1084. }
  1085.  
  1086. vector<int> choices;
  1087. vector<int> covered(ndancers,0);
  1088. vector<bool> chosen(nsongs,0);
  1089.  
  1090. int curans = 0;
  1091. int bestprefix = 0;
  1092. int bestans = 0;
  1093.  
  1094. while (1) {
  1095. int choice = -1, best = 0;
  1096. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1097. int num = 0;
  1098. for (int j=0;j<ndancers;++j) {
  1099. if (v[j][i]) {
  1100. if (!covered[j] && bored[j]>0) {
  1101. num += 1000*(nsongs-bored[j]);
  1102. }
  1103. else if (covered[j] && bored[j]>0) {
  1104. num += 5;
  1105. }
  1106. }
  1107. else {
  1108. if (covered[j] && bored[j]==1) {
  1109. num -= 1000*nsongs;
  1110. }
  1111. else if (bored[j]==1) {
  1112. num -= 1000*nsongs;
  1113. }
  1114. }
  1115. }
  1116.  
  1117. if (num > best || (num>=best && (rand()&1))) {
  1118. choice = i;
  1119. best = num;
  1120. }
  1121. }
  1122. if (choice==-1) break;
  1123.  
  1124. // Update for each dancer whether covered or not (and the boredom)
  1125. for (int j=0;j<ndancers;++j) {
  1126. if (v[j][choice]) {
  1127. ++covered[j];
  1128. if (covered[j] == 1 && bored[j]>0) {
  1129. ++curans;
  1130. }
  1131. }
  1132. else {
  1133. --bored[j];
  1134. if (bored[j]==0 && covered[j]) {
  1135. --curans;
  1136. }
  1137. }
  1138. }
  1139.  
  1140. chosen[choice] = 1;
  1141. choices.push_back(choice);
  1142.  
  1143. if (curans > bestans) {
  1144. bestans = curans;
  1145. bestprefix = choices.size();
  1146. }
  1147. }
  1148. if (bestans > BEST_SOL) {
  1149. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1150. BEST_SOL = bestans;
  1151. }
  1152. }
  1153. //}}}
  1154. // END GREEDY 3
  1155.  
  1156. // GREEDY SET COVER SOLUTION 4
  1157. //{{{
  1158. void greedy4(const vvi& v) {
  1159. if (BEST_SOL == v.size()-1)
  1160. return;
  1161.  
  1162. int ndancers = v.size()-1;
  1163. int nsongs = v[0].size()-1;
  1164.  
  1165. vector<int> contained_in(ndancers,0);
  1166. for (int j=0;j<ndancers;++j) {
  1167. for (int i=0;i<nsongs;++i) {
  1168. if (v[j][i]) {
  1169. ++contained_in[j];
  1170. }
  1171. }
  1172. }
  1173.  
  1174. vector<int> bored(ndancers);
  1175. for (int i=0;i<ndancers;++i) {
  1176. bored[i] = v[i][nsongs];
  1177. }
  1178.  
  1179. vector<int> choices;
  1180. vector<int> covered(ndancers,0);
  1181. vector<bool> chosen(nsongs,0);
  1182.  
  1183. int curans = 0;
  1184. int bestprefix = 0;
  1185. int bestans = 0;
  1186.  
  1187. while (1) {
  1188. int choice = -1, best = 0;
  1189. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1190. int num = 0;
  1191. for (int j=0;j<ndancers;++j) {
  1192. if (v[j][i]) {
  1193. if (!covered[j] && bored[j]>0) {
  1194. //++num;
  1195. num += 4*v[j][nsongs] + 10000 + 11*(nsongs-contained_in[j]);
  1196. }
  1197. else if (covered[j] && bored[j]>0) {
  1198. num += 5;
  1199. }
  1200. }
  1201. else {
  1202. if (covered[j] && bored[j]==1) {
  1203. //--num;
  1204. num -= 10000;
  1205. }
  1206. else if (bored[j]==1) {
  1207. num -= 1000;
  1208. }
  1209. }
  1210. }
  1211.  
  1212. if (num > best || (num>=best && (rand()&1))) {
  1213. choice = i;
  1214. best = num;
  1215. }
  1216. }
  1217. if (choice==-1) break;
  1218.  
  1219. // Update for each dancer whether covered or not (and the boredom)
  1220. for (int j=0;j<ndancers;++j) {
  1221. if (v[j][choice]) {
  1222. ++covered[j];
  1223. if (covered[j] == 1 && bored[j]>0) {
  1224. ++curans;
  1225. }
  1226. }
  1227. else {
  1228. --bored[j];
  1229. if (bored[j]==0 && covered[j]) {
  1230. --curans;
  1231. }
  1232. }
  1233. }
  1234.  
  1235. chosen[choice] = 1;
  1236. choices.push_back(choice);
  1237.  
  1238. if (curans > bestans) {
  1239. bestans = curans;
  1240. bestprefix = choices.size();
  1241. }
  1242. }
  1243.  
  1244. if (bestans > BEST_SOL) {
  1245. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1246. BEST_SOL = bestans;
  1247. }
  1248. }
  1249. //}}}
  1250. // END GREEDY
  1251.  
  1252. // GREEDY SET COVER SOLUTION 5
  1253. //{{{
  1254. void greedy5(const vvi& v) {
  1255. if (BEST_SOL == v.size()-1)
  1256. return;
  1257.  
  1258. int ndancers = v.size()-1;
  1259. int nsongs = v[0].size()-1;
  1260.  
  1261. vector<int> contained_in(ndancers,0);
  1262. for (int j=0;j<ndancers;++j) {
  1263. for (int i=0;i<nsongs;++i) {
  1264. if (v[j][i]) {
  1265. ++contained_in[j];
  1266. }
  1267. }
  1268. }
  1269.  
  1270. vector<int> bored(ndancers);
  1271. for (int i=0;i<ndancers;++i) {
  1272. bored[i] = v[i][nsongs];
  1273. }
  1274.  
  1275. vector<int> choices;
  1276. vector<int> covered(ndancers,0);
  1277. vector<bool> chosen(nsongs,0);
  1278.  
  1279. int curans = 0;
  1280. int bestprefix = 0;
  1281. int bestans = 0;
  1282.  
  1283. while (1) {
  1284. int choice = -1, best = 0;
  1285. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1286. int num = 0;
  1287. for (int j=0;j<ndancers;++j) {
  1288. if (v[j][i]) {
  1289. if (!covered[j] && bored[j]>0) {
  1290. //++num;
  1291. num += 7*v[j][nsongs] + 10000 + 30*(nsongs-contained_in[j]);
  1292. }
  1293. else if (covered[j] && bored[j]>0) {
  1294. num += 10;
  1295. }
  1296. }
  1297. else {
  1298. if (covered[j] && bored[j]==1) {
  1299. //--num;
  1300. num -= 10000;
  1301. }
  1302. else if (bored[j]==1) {
  1303. num -= 5000;
  1304. }
  1305. }
  1306. }
  1307.  
  1308. if (num > best || (num>=best && (rand()&1))) {
  1309. choice = i;
  1310. best = num;
  1311. }
  1312. }
  1313. if (choice==-1) break;
  1314.  
  1315. // Update for each dancer whether covered or not (and the boredom)
  1316. for (int j=0;j<ndancers;++j) {
  1317. if (v[j][choice]) {
  1318. ++covered[j];
  1319. if (covered[j] == 1 && bored[j]>0) {
  1320. ++curans;
  1321. }
  1322. }
  1323. else {
  1324. --bored[j];
  1325. if (bored[j]==0 && covered[j]) {
  1326. --curans;
  1327. }
  1328. }
  1329. }
  1330.  
  1331. chosen[choice] = 1;
  1332. choices.push_back(choice);
  1333.  
  1334. if (curans > bestans) {
  1335. bestans = curans;
  1336. bestprefix = choices.size();
  1337. }
  1338. }
  1339.  
  1340. if (bestans > BEST_SOL) {
  1341. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1342. BEST_SOL = bestans;
  1343. }
  1344. }
  1345. //}}}
  1346. // END GREEDY
  1347.  
  1348. // GREEDY SET COVER SOLUTION 6
  1349. //{{{
  1350. void greedy6(const vvi& v) {
  1351. if (BEST_SOL == v.size()-1)
  1352. return;
  1353.  
  1354. int ndancers = v.size()-1;
  1355. int nsongs = v[0].size()-1;
  1356.  
  1357. vector<int> contained_in(ndancers,0);
  1358. for (int j=0;j<ndancers;++j) {
  1359. for (int i=0;i<nsongs;++i) {
  1360. if (v[j][i]) {
  1361. ++contained_in[j];
  1362. }
  1363. }
  1364. }
  1365.  
  1366. vector<int> bored(ndancers);
  1367. for (int i=0;i<ndancers;++i) {
  1368. bored[i] = v[i][nsongs];
  1369. if (bored[i]<=5) bored[i]=0;
  1370. }
  1371.  
  1372. vector<int> choices;
  1373. vector<int> covered(ndancers,0);
  1374. vector<bool> chosen(nsongs,0);
  1375.  
  1376. int curans = 0;
  1377. int bestprefix = 0;
  1378. int bestans = 0;
  1379.  
  1380. while (1) {
  1381. int choice = -1, best = 0;
  1382. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1383. int num = 0;
  1384. for (int j=0;j<ndancers;++j) {
  1385. if (v[j][i]) {
  1386. if (!covered[j] && bored[j]>0) {
  1387. //++num;
  1388. num += /*v[j][nsongs]*/ + 10000 + (nsongs-contained_in[j]);
  1389. }
  1390. else if (covered[j] && bored[j]>0) {
  1391. //num += 20;
  1392. }
  1393. }
  1394. else {
  1395. if (covered[j] && bored[j]==1) {
  1396. //--num;
  1397. num -= 10000;
  1398. }
  1399. }
  1400. }
  1401.  
  1402. if (num > best || (num>=best && (rand()&1))) {
  1403. choice = i;
  1404. best = num;
  1405. }
  1406. }
  1407. if (choice==-1) break;
  1408.  
  1409. // Update for each dancer whether covered or not (and the boredom)
  1410. for (int j=0;j<ndancers;++j) {
  1411. if (v[j][choice]) {
  1412. ++covered[j];
  1413. if (covered[j] == 1 && bored[j]>0) {
  1414. ++curans;
  1415. }
  1416. }
  1417. else {
  1418. --bored[j];
  1419. if (bored[j]==0 && covered[j]) {
  1420. --curans;
  1421. }
  1422. }
  1423. }
  1424.  
  1425. chosen[choice] = 1;
  1426. choices.push_back(choice);
  1427.  
  1428. if (curans > bestans) {
  1429. bestans = curans;
  1430. bestprefix = choices.size();
  1431. }
  1432. }
  1433.  
  1434. if (bestans > BEST_SOL) {
  1435. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1436. BEST_SOL = bestans;
  1437. }
  1438. }
  1439. //}}}
  1440. // END GREEDY
  1441.  
  1442. // GREEDY SET COVER SOLUTION 7
  1443. //{{{
  1444. void greedy7(const vvi& v) {
  1445. if (BEST_SOL == v.size()-1)
  1446. return;
  1447.  
  1448. int ndancers = v.size()-1;
  1449. int nsongs = v[0].size()-1;
  1450.  
  1451. vector<int> contained_in(ndancers,0);
  1452. for (int j=0;j<ndancers;++j) {
  1453. for (int i=0;i<nsongs;++i) {
  1454. if (v[j][i]) {
  1455. ++contained_in[j];
  1456. }
  1457. }
  1458. }
  1459.  
  1460. vector<int> bored(ndancers);
  1461. for (int i=0;i<ndancers;++i) {
  1462. bored[i] = v[i][nsongs];
  1463. }
  1464.  
  1465. vector<int> choices;
  1466. vector<int> covered(ndancers,0);
  1467. vector<bool> chosen(nsongs,0);
  1468.  
  1469. int curans = 0;
  1470. int bestprefix = 0;
  1471. int bestans = 0;
  1472.  
  1473. while (1) {
  1474. int choice = -1, best = 0;
  1475. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1476. int num = 0;
  1477. for (int j=0;j<ndancers;++j) {
  1478. if (v[j][i]) {
  1479. if (!covered[j] && bored[j]>0) {
  1480. //++num;
  1481. num += 1000000 + 1000*(nsongs-contained_in[j]);
  1482. }
  1483. else if (covered[j] && bored[j]>0) {
  1484. //num += 5;
  1485. }
  1486. }
  1487. else {
  1488. if (covered[j] && bored[j]==1) {
  1489. //--num;
  1490. num -= 1000000;
  1491. }
  1492. else if (bored[j]==1) {
  1493. num -= 500000;
  1494. }
  1495. }
  1496. }
  1497.  
  1498. if (num > best || (num>=best && (rand()&1))) {
  1499. choice = i;
  1500. best = num;
  1501. }
  1502. }
  1503. if (choice==-1) break;
  1504.  
  1505. // Update for each dancer whether covered or not (and the boredom)
  1506. for (int j=0;j<ndancers;++j) {
  1507. if (v[j][choice]) {
  1508. ++covered[j];
  1509. if (covered[j] == 1 && bored[j]>0) {
  1510. ++curans;
  1511. }
  1512. }
  1513. else {
  1514. --bored[j];
  1515. if (bored[j]==0 && covered[j]) {
  1516. --curans;
  1517. }
  1518. }
  1519. }
  1520.  
  1521. chosen[choice] = 1;
  1522. choices.push_back(choice);
  1523.  
  1524. if (curans > bestans) {
  1525. bestans = curans;
  1526. bestprefix = choices.size();
  1527. }
  1528. }
  1529.  
  1530. if (bestans > BEST_SOL) {
  1531. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1532. BEST_SOL = bestans;
  1533. }
  1534. }
  1535. //}}}
  1536. // END GREEDY
  1537.  
  1538. // GREEDY SET COVER SOLUTION 8
  1539. //{{{
  1540. void greedy8(const vvi& v) {
  1541. if (BEST_SOL == v.size()-1)
  1542. return;
  1543.  
  1544. int ndancers = v.size()-1;
  1545. int nsongs = v[0].size()-1;
  1546.  
  1547. vector<int> contained_in(ndancers,0);
  1548. for (int j=0;j<ndancers;++j) {
  1549. for (int i=0;i<nsongs;++i) {
  1550. if (v[j][i]) {
  1551. ++contained_in[j];
  1552. }
  1553. }
  1554. }
  1555.  
  1556. vector<int> bored(ndancers);
  1557. for (int i=0;i<ndancers;++i) {
  1558. bored[i] = v[i][nsongs];
  1559. }
  1560.  
  1561. vector<int> choices;
  1562. vector<int> covered(ndancers,0);
  1563. vector<bool> chosen(nsongs,0);
  1564.  
  1565. int curans = 0;
  1566. int bestprefix = 0;
  1567. int bestans = 0;
  1568.  
  1569. while (1) {
  1570. int choice = -1, best = 0;
  1571. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1572. int num = 0;
  1573. for (int j=0;j<ndancers;++j) {
  1574. if (v[j][i]) {
  1575. if (bored[j]>0) {
  1576. num += 1000*(nsongs-bored[j]);
  1577. }
  1578. }
  1579. else {
  1580. if (bored[j]>0) {
  1581. num -= 1000*(nsongs-bored[j]);
  1582. }
  1583. }
  1584. }
  1585.  
  1586. if (num > best || (num>=best && (rand()&1))) {
  1587. choice = i;
  1588. best = num;
  1589. }
  1590. }
  1591. if (choice==-1) break;
  1592.  
  1593. // Update for each dancer whether covered or not (and the boredom)
  1594. for (int j=0;j<ndancers;++j) {
  1595. if (v[j][choice]) {
  1596. ++covered[j];
  1597. if (covered[j] == 1 && bored[j]>0) {
  1598. ++curans;
  1599. }
  1600. }
  1601. else {
  1602. --bored[j];
  1603. if (bored[j]==0 && covered[j]) {
  1604. --curans;
  1605. }
  1606. }
  1607. }
  1608.  
  1609. chosen[choice] = 1;
  1610. choices.push_back(choice);
  1611.  
  1612. if (curans > bestans) {
  1613. bestans = curans;
  1614. bestprefix = choices.size();
  1615. }
  1616. }
  1617.  
  1618. if (bestans > BEST_SOL) {
  1619. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1620. BEST_SOL = bestans;
  1621. }
  1622. }
  1623. //}}}
  1624. // END GREEDY
  1625.  
  1626. // GREEDY SET COVER SOLUTION 9
  1627. //{{{
  1628. void greedy9(const vvi& v) {
  1629. if (BEST_SOL == v.size()-1)
  1630. return;
  1631.  
  1632. int ndancers = v.size()-1;
  1633. int nsongs = v[0].size()-1;
  1634.  
  1635. vector<int> contained_in(ndancers,0);
  1636. for (int j=0;j<ndancers;++j) {
  1637. for (int i=0;i<nsongs;++i) {
  1638. if (v[j][i]) {
  1639. ++contained_in[j];
  1640. }
  1641. }
  1642. }
  1643.  
  1644. vector<int> bored(ndancers);
  1645. for (int i=0;i<ndancers;++i) {
  1646. bored[i] = v[i][nsongs];
  1647. }
  1648.  
  1649. vector<int> choices;
  1650. vector<int> covered(ndancers,0);
  1651. vector<bool> chosen(nsongs,0);
  1652.  
  1653. int curans = 0;
  1654. int bestprefix = 0;
  1655. int bestans = 0;
  1656.  
  1657. while (1) {
  1658. int choice = -1, best = 0;
  1659. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1660. int num = 0;
  1661. for (int j=0;j<ndancers;++j) {
  1662. if (v[j][i]) {
  1663. if (!covered[j] && bored[j]>0) {
  1664. num += sqr(sqr(nsongs-bored[j]));
  1665. }
  1666. else if (covered[j] && bored[j]>0) {
  1667. num += 1;
  1668. }
  1669. }
  1670. else {
  1671. if (covered[j] && bored[j]==1) {
  1672. num -= 10000000;
  1673. }
  1674. }
  1675. }
  1676.  
  1677. if (num > best || (num>=best && (rand()&1))) {
  1678. choice = i;
  1679. best = num;
  1680. }
  1681. }
  1682. if (choice==-1) break;
  1683.  
  1684. // Update for each dancer whether covered or not (and the boredom)
  1685. for (int j=0;j<ndancers;++j) {
  1686. if (v[j][choice]) {
  1687. ++covered[j];
  1688. if (covered[j] == 1 && bored[j]>0) {
  1689. ++curans;
  1690. }
  1691. }
  1692. else {
  1693. --bored[j];
  1694. if (bored[j]==0 && covered[j]) {
  1695. --curans;
  1696. }
  1697. }
  1698. }
  1699.  
  1700. chosen[choice] = 1;
  1701. choices.push_back(choice);
  1702.  
  1703. if (curans > bestans) {
  1704. bestans = curans;
  1705. bestprefix = choices.size();
  1706. }
  1707. }
  1708.  
  1709. if (bestans > BEST_SOL) {
  1710. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1711. BEST_SOL = bestans;
  1712. }
  1713. }
  1714. //}}}
  1715. // END GREEDY
  1716.  
  1717. // GREEDY SET COVER SOLUTION 10
  1718. //{{{
  1719. void greedy10(const vvi& v) {
  1720. if (BEST_SOL == v.size()-1)
  1721. return;
  1722.  
  1723. int ndancers = v.size()-1;
  1724. int nsongs = v[0].size()-1;
  1725.  
  1726. vector<int> contained_in(ndancers,0);
  1727. for (int j=0;j<ndancers;++j) {
  1728. for (int i=0;i<nsongs;++i) {
  1729. if (v[j][i]) {
  1730. ++contained_in[j];
  1731. }
  1732. }
  1733. }
  1734.  
  1735. vector<int> bored(ndancers);
  1736. for (int i=0;i<ndancers;++i) {
  1737. bored[i] = v[i][nsongs];
  1738. }
  1739.  
  1740. vector<int> choices;
  1741. vector<int> covered(ndancers,0);
  1742. vector<bool> chosen(nsongs,0);
  1743.  
  1744. int curans = 0;
  1745. int bestprefix = 0;
  1746. int bestans = 0;
  1747.  
  1748. while (1) {
  1749. int choice = -1, best = 0;
  1750. for (int i=0;i<nsongs;++i) if (!chosen[i]) {
  1751. int num = 0;
  1752. for (int j=0;j<ndancers && num!=-1;++j) {
  1753. if (v[j][i]) {
  1754. if (!covered[j] && bored[j]>0) {
  1755. num += sqr(nsongs+1-bored[j]);
  1756. }
  1757. else if (covered[j] && bored[j]>0) {
  1758. num += 1;
  1759. }
  1760. }
  1761. else {
  1762. if (covered[j] && bored[j]==1) {
  1763. num = -1;
  1764. }
  1765. else if (bored[j]==1) {
  1766. num = -1;
  1767. }
  1768. }
  1769. }
  1770.  
  1771. if (num > best || (num>=best && (rand()&1))) {
  1772. choice = i;
  1773. best = num;
  1774. }
  1775. }
  1776. if (choice==-1) break;
  1777.  
  1778. // Update for each dancer whether covered or not (and the boredom)
  1779. for (int j=0;j<ndancers;++j) {
  1780. if (v[j][choice]) {
  1781. ++covered[j];
  1782. if (covered[j] == 1 && bored[j]>0) {
  1783. ++curans;
  1784. }
  1785. }
  1786. else {
  1787. --bored[j];
  1788. if (bored[j]==0 && covered[j]) {
  1789. --curans;
  1790. }
  1791. }
  1792. }
  1793.  
  1794. chosen[choice] = 1;
  1795. choices.push_back(choice);
  1796.  
  1797. if (curans > bestans) {
  1798. bestans = curans;
  1799. bestprefix = choices.size();
  1800. }
  1801. }
  1802.  
  1803. if (bestans > BEST_SOL) {
  1804. REAL_ANS = vector<int>(choices.begin(),choices.begin()+bestprefix);
  1805. BEST_SOL = bestans;
  1806. }
  1807. }
  1808. //}}}
  1809. // END GREEDY
  1810.  
  1811. // BACKTRACKING
  1812. //{{{
  1813. const int MAX=501;
  1814. int B_bored[MAX];
  1815. int B_ans;
  1816. int B_covered[MAX];
  1817. int B_ndancers;
  1818. int B_nsongs;
  1819. int B_selected[MAX];
  1820. int B_MAXITS;
  1821. int B_countones[MAX];
  1822. int B_outbored;
  1823.  
  1824. void setup_backtracking(const vvi& v, int iterations) {
  1825. B_MAXITS = iterations;
  1826. B_ndancers = v.size()-1;
  1827. B_nsongs = v[0].size()-1;
  1828. B_outbored = 0;
  1829.  
  1830. if (BEST_SOL == B_ndancers) {
  1831. B_MAXITS=0;
  1832. return;
  1833. }
  1834.  
  1835. for (int i=0;i<B_ndancers;++i) {
  1836. B_bored[i] = v[i][B_nsongs];
  1837. B_covered[i] = 0;
  1838. }
  1839. B_ans = 0;
  1840. }
  1841.  
  1842. void backtrack(const vvi& v, int at, int i, int rem) {
  1843. if (B_ans > BEST_SOL) { // Update to a better solution
  1844. //printf("UPDATE TO %d\n", B_ans);
  1845. BEST_SOL = B_ans;
  1846. REAL_ANS.clear();
  1847. for (int k=0;k<at;++k) {
  1848. REAL_ANS.push_back(B_selected[k]);
  1849. }
  1850. if (BEST_SOL == B_ndancers) {
  1851. B_MAXITS = 0;
  1852. return;
  1853. }
  1854. }
  1855.  
  1856. if (rem==0 || i >= B_nsongs) return;
  1857. if (B_ndancers - B_outbored <= BEST_SOL) return;
  1858.  
  1859. --B_MAXITS;
  1860. if (B_MAXITS <= 0) return;
  1861.  
  1862. int prev_ans = B_ans;
  1863.  
  1864. for (int j=0;j<B_ndancers;++j) {
  1865. if (v[j][i]) {
  1866. ++B_covered[j];
  1867. if (B_covered[j]==1 && B_bored[j]>0) ++B_ans;
  1868. }
  1869. else {
  1870. if (B_bored[j]==1) {
  1871. if (B_covered[j]) --B_ans;
  1872. ++B_outbored;
  1873. }
  1874. --B_bored[j];
  1875. }
  1876. }
  1877.  
  1878. if (B_ans > prev_ans) {
  1879. B_selected[at] = i;
  1880. backtrack(v, at+1, i+1,rem-1);
  1881. }
  1882.  
  1883. for (int j=0;j<B_ndancers;++j) {
  1884. if (v[j][i]) {
  1885. --B_covered[j];
  1886. if (B_covered[j]==0 && B_bored[j]>0) --B_ans;
  1887. }
  1888. else {
  1889. ++B_bored[j];
  1890. if (B_bored[j]==1) {
  1891. if (B_covered[j]) ++B_ans;
  1892. --B_outbored;
  1893. }
  1894. }
  1895. }
  1896.  
  1897. backtrack(v, at, i+1,rem);
  1898. }
  1899. //}}}
  1900. // END BACKTRACKING
  1901.  
  1902. // OPTIMIZE THE INSTANCE
  1903. //{{{
  1904. vvi delete_zero_rows(const vvi& v) {
  1905. vvi ret;
  1906. for (int i=0;i<v.size();++i) {
  1907. bool allzero = 1;
  1908. for (int j=0;j+1<v[i].size();++j) {
  1909. if (v[i][j]!=0) { allzero = 0; break; }
  1910. }
  1911. if (!allzero) ret.push_back(v[i]);
  1912. }
  1913. return ret;
  1914. }
  1915.  
  1916. vvi transpose(const vvi& v) {
  1917. vvi ret(v[0].size(),vector<int>(v.size()));
  1918. for (int i=0;i<v.size();++i)
  1919. for (int j=0;j<v[i].size();++j)
  1920. ret[j][i] = v[i][j];
  1921. return ret;
  1922. }
  1923.  
  1924. vvi remove_redundant_rows(const vvi& v) {
  1925. vvi ret;
  1926. int m = v.size()-1, n = v[0].size()-1;
  1927.  
  1928. vector<vector<unsigned int> > bits(m);
  1929. for (int i=0;i<m;++i) {
  1930. for (int j=0;j<n;j+=32) {
  1931. unsigned int cur = 0;
  1932. for (int k=0;k<32 && j+k<n;++k) {
  1933. if (v[i][j+k]==1) {
  1934. cur |= (1u<<k);
  1935. }
  1936. }
  1937. bits[i].push_back(cur);
  1938. }
  1939. }
  1940.  
  1941. vector<bool> keep(m,1);
  1942. for (int i=0;i<m;++i) if (keep[i]) {
  1943. for (int j=i+1;j<m;++j) if (keep[j]) {
  1944. bool kill = 1;
  1945. for (int k=0;k<bits[i].size();++k) {
  1946. if ( (bits[i][k] & bits[j][k]) != bits[j][k]) {
  1947. kill = 0;
  1948. break;
  1949. }
  1950. }
  1951. if (kill) {
  1952. keep[j] = 0;
  1953. }
  1954. }
  1955. }
  1956.  
  1957. for (int i=0;i<m;++i) if (keep[i]) {
  1958. ret.push_back(v[i]);
  1959. }
  1960. ret.push_back(v.back());
  1961. return ret;
  1962. }
  1963.  
  1964. template<class T> inline int BITCNT(T x){int r=0;while(x){r++;x&=x-1;}return r;}
  1965.  
  1966. vvi remove_redundant_rows_bounded2(const vvi& v) {
  1967. vvi ret;
  1968. int m = v.size()-1, n = v[0].size()-1;
  1969.  
  1970. vector<vector<unsigned int> > bits(m);
  1971. for (int i=0;i<m;++i) {
  1972. for (int j=0;j<n;j+=32) {
  1973. unsigned int cur = 0;
  1974. for (int k=0;k<32 && j+k<n;++k) {
  1975. if (v[i][j+k]==1) {
  1976. cur |= (1u<<k);
  1977. }
  1978. }
  1979. bits[i].push_back(cur);
  1980. }
  1981. }
  1982.  
  1983. const int B = 40;
  1984.  
  1985. vector<bool> keep(m,1);
  1986. for (int i=0;i<m;++i) if (keep[i]) {
  1987. for (int j=i+1;j<m;++j) if (keep[j]) {
  1988. int diff = 0;
  1989. for (int k=0;k<bits[i].size() && diff <= B;++k) {
  1990. diff += BITCNT(bits[i][k] ^ bits[j][k]);
  1991. }
  1992. if (diff<=B) {
  1993. keep[j] = 0;
  1994. }
  1995. }
  1996. }
  1997.  
  1998. for (int i=0;i<m;++i) if (keep[i]) {
  1999. ret.push_back(v[i]);
  2000. }
  2001. ret.push_back(v.back());
  2002. return ret;
  2003. }
  2004. vvi remove_redundant_rows_bounded(const vvi& v, const int bound) {
  2005. if (bound==-1) return remove_redundant_rows_bounded2(v);
  2006. vvi ret;
  2007. int m = v.size()-1, n = v[0].size()-1;
  2008.  
  2009. vector<vector<unsigned int> > bits(m);
  2010. for (int i=0;i<m;++i) {
  2011. for (int j=0;j<n;j+=32) {
  2012. unsigned int cur = 0;
  2013. for (int k=0;k<32 && j+k<n;++k) {
  2014. if (v[i][j+k]==1 && v[m][j+k] <= bound) {
  2015. cur |= (1u<<k);
  2016. }
  2017. }
  2018. bits[i].push_back(cur);
  2019. }
  2020. }
  2021.  
  2022. vector<bool> keep(m,1);
  2023. for (int i=0;i<m;++i) if (keep[i]) {
  2024. for (int j=i+1;j<m;++j) if (keep[j]) {
  2025. bool kill = 1;
  2026. for (int k=0;k<bits[i].size();++k) {
  2027. if ( (bits[i][k] & bits[j][k]) != bits[j][k]) {
  2028. kill = 0;
  2029. break;
  2030. }
  2031. }
  2032. if (kill) {
  2033. //cerr << "\t KILL " << j << " BOUND " << bound << endl;
  2034. keep[j] = 0;
  2035. }
  2036. }
  2037. }
  2038.  
  2039. for (int i=0;i<m;++i) if (keep[i]) {
  2040. ret.push_back(v[i]);
  2041. }
  2042. ret.push_back(v.back());
  2043. return ret;
  2044. }
  2045.  
  2046.  
  2047. vvi remove_one_rows(const vvi& v) {
  2048. int m = v.size()-1, n = v[0].size()-1;
  2049. vector<bool> keep(m,1);
  2050. for (int j=0;j<n;++j) if (v[m][j]==1) {
  2051. for (int i=0;i<m;++i) if (v[i][j] == 0) {
  2052. keep[i] = 0;
  2053. }
  2054. }
  2055.  
  2056. vvi ret;
  2057. for (int i=0;i<m;++i) if (keep[i]) {
  2058. ret.push_back(v[i]);
  2059. }
  2060. ret.push_back(v.back());
  2061. return ret;
  2062. }
  2063. //}}}
  2064. // END OPTIMIZE THE INSTANCE
  2065.  
  2066. // UTILITY FUNCTIONS
  2067. //{{{
  2068. int count_ones(const vector<int>& v) {
  2069. int ans = 0;
  2070. for (int i=0;i+1<v.size();++i) ans += v[i];
  2071. return ans;
  2072. }
  2073. int rate(const vvi& v, int i) {
  2074. int NSONGS = v.size()-1;
  2075. int ans = 0;
  2076. for (int j=0;j+1<v[i].size();++j) if (v[i][j] && v[NSONGS][j]>=15) {
  2077. ans += 100000;
  2078. }
  2079. return ans;
  2080. }
  2081. void show(const vvi& v) {
  2082. for (int i=0;i<v.size();++i) {
  2083. for (int j=0;j<v[i].size();++j) {
  2084. cerr << v[i][j] << " ";
  2085. }
  2086. cerr << endl;
  2087. }
  2088. }
  2089. vvi remove_boredom_bound(const vvi& v, const int bound) {
  2090. int m = v.size()-1, n = v[0].size()-1;
  2091. vvi ret;
  2092. for (int i=0;i<m;++i) if (v[i][n]>bound) ret.push_back(v[i]);
  2093. ret.push_back(v.back());
  2094. return ret;
  2095. }
  2096. //}}}
  2097. // END UTILITY FUNCTIONS
  2098.  
  2099. pair<int, vector<int> > realsolve(vvi& L, const int BOUND=1<<30) {
  2100. int PREVANS = BEST_SOL;
  2101.  
  2102. { // Make some simple transformations on L
  2103. L = delete_zero_rows(L);
  2104. L = transpose(L);
  2105. L = delete_zero_rows(L);
  2106.  
  2107. {
  2108. vector<pair<int,int> > ones_sort(L.size());
  2109. for (int i=0;i+1<L.size();++i) {
  2110. ones_sort[i] = make_pair(count_ones(L[i]),i);
  2111. }
  2112. sort(ones_sort.begin(),--ones_sort.end(),greater<pair<int,int> >());
  2113.  
  2114. {
  2115. vvi NL(L.size());
  2116. for (int i=0;i<ones_sort.size();++i) {
  2117. NL[i] = L[ones_sort[i].second];
  2118. }
  2119. NL.back() = L.back();
  2120. L = NL;
  2121. }
  2122. }
  2123.  
  2124. L = remove_redundant_rows_bounded(L, BOUND);
  2125. L = transpose(L);
  2126. }
  2127.  
  2128. greedy(L); greedy(L); greedy(L); greedy(L); greedy(L); greedy(L); greedy(L);
  2129. greedy2(L); greedy2(L);
  2130. greedy3(L); greedy3(L);
  2131. greedy4(L); greedy4(L);
  2132. greedy5(L); greedy5(L);
  2133. greedy6(L); greedy6(L);
  2134. greedy7(L); greedy7(L);
  2135. greedy8(L); greedy8(L);
  2136. greedy9(L); greedy9(L);
  2137. greedy10(L); greedy10(L);
  2138.  
  2139. { // Do some greedy backtracking
  2140. int NUMDANCERS = L.size()-1;
  2141. int NUMSONGS = L[0].size()-1;
  2142.  
  2143. setup_greedy_backtracking(L, 90000000/(6*NUMDANCERS*NUMSONGS));
  2144. greedy_with_backtracking2(L,0);
  2145.  
  2146. setup_greedy_backtracking(L, 90000000/(6*NUMDANCERS*NUMSONGS));
  2147. greedy_with_backtracking8(L,0);
  2148.  
  2149. /*
  2150. setup_greedy_backtracking(L, 100000000/(6*NUMDANCERS*NUMSONGS));
  2151. greedy_with_backtracking10(L,0);
  2152. */
  2153.  
  2154. /*
  2155. setup_greedy_backtracking(L, 100000000/(6*NUMDANCERS*NUMSONGS));
  2156. greedy_with_backtracking3(L,0);
  2157. */
  2158.  
  2159. /*
  2160. setup_greedy_backtracking(L, 200000000/(6*NUMDANCERS*NUMSONGS));
  2161. greedy_with_backtracking4(L,0);
  2162. */
  2163.  
  2164. /*
  2165. setup_greedy_backtracking(L, 200000000/(6*NUMDANCERS*NUMSONGS));
  2166. greedy_with_backtracking5(L,0);
  2167. */
  2168.  
  2169. /*
  2170. setup_greedy_backtracking(L, 200000000/(6*NUMDANCERS*NUMSONGS));
  2171. greedy_with_backtracking6(L,0);
  2172. */
  2173.  
  2174. /*
  2175. setup_greedy_backtracking(L, 200000000/(6*NUMDANCERS*NUMSONGS));
  2176. greedy_with_backtracking7(L,0);
  2177. */
  2178.  
  2179.  
  2180. /*
  2181. setup_greedy_backtracking(L, 100000000/(6*NUMDANCERS*NUMSONGS));
  2182. greedy_with_backtracking9(L,0, 0);
  2183. */
  2184. }
  2185.  
  2186. /*
  2187. {
  2188. int NUMDANCERS = L[0].size()-1;
  2189. //setup_backtracking(L, 500000000/(6*NUMDANCERS));
  2190. setup_backtracking(L, 1<<30);
  2191. backtrack(L,0,0,25);
  2192. }
  2193. */
  2194.  
  2195. done:
  2196. if (BEST_SOL > PREVANS) {
  2197. vector<int> ret(REAL_ANS.size());
  2198. for (int i=0;i<REAL_ANS.size();++i) {
  2199. ret[i] = L[L.size()-1][REAL_ANS[i]];
  2200. }
  2201. return make_pair(BEST_SOL, ret);
  2202. }
  2203. else {
  2204. return make_pair(0, vector<int>());
  2205. }
  2206. }
  2207.  
  2208. void do_output(const vector<int>& v) {
  2209. assert(v.size()<=25);
  2210. printf("%d\n", v.size());
  2211. for (int i=0;i<v.size();++i) printf("%d\n", v[i]);
  2212. }
  2213.  
  2214. bool solve(bool output) {
  2215. int D,S;
  2216.  
  2217. GETNUM(D);
  2218. GETNUM(S);
  2219.  
  2220. vector<int> B(D);
  2221. vvi L(D+1,vector<int>(S+1,0));
  2222. for (int i=0;i<D;++i) {
  2223. GETNUM(B[i]);
  2224. }
  2225.  
  2226. for (int i=0;i<D;++i) {
  2227. for (int j=0;j<S;++j) {
  2228. GETNUM(L[i][j]);
  2229. }
  2230. // Append the boredom for each dancer
  2231. L[i][S] = B[i];
  2232. }
  2233. // Name of the songs as an extra row.
  2234. for (int i=0;i<S;++i) {
  2235. L[D][i] = i;
  2236. }
  2237.  
  2238. BEST_SOL = 0;
  2239. REAL_ANS.clear();
  2240. srand(time(NULL));
  2241.  
  2242. pair<int,vector<int> > p0 = realsolve(L);
  2243. if (L.size()-1 == p0.first) { // optimal solution
  2244. if (output) do_output(p0.second);
  2245. return 1;
  2246. }
  2247.  
  2248. vector<int>& ans = p0.second;
  2249.  
  2250. const vvi copyL = L;
  2251.  
  2252. if (L.size()-1 > BEST_SOL && L[0].size()>1) {
  2253. int PREV_SOL = BEST_SOL;
  2254. pair<int,vector<int> > p1 = realsolve(L,30);
  2255. #ifndef ONLINE_JUDGE
  2256. cerr << "\t1: TRYING HERE " << L.size()-1 << " AND NSONGS " << L[0].size() - 1 << " GET " << BEST_SOL << " PREV " << PREV_SOL << endl;
  2257. #endif
  2258. if (p1.first > PREV_SOL) {
  2259. #ifdef ONLINE_JUDGE
  2260. #endif
  2261. ans = p1.second;
  2262. }
  2263. }
  2264.  
  2265. if (L.size()-1 > BEST_SOL && L[0].size()>1) {
  2266. L = copyL;
  2267.  
  2268. int PREV_SOL = BEST_SOL;
  2269. pair<int,vector<int> > p2 = realsolve(L,-1);
  2270. #ifndef ONLINE_JUDGE
  2271. cerr << "\t2: TRYING HERE " << L.size()-1 << " AND NSONGS " << L[0].size() - 1 << " GET " << BEST_SOL << " PREV " << PREV_SOL << endl;
  2272. #endif
  2273. if (p2.first > PREV_SOL) {
  2274. #ifdef ONLINE_JUDGE
  2275. assert(0);
  2276. #endif
  2277. ans = p2.second;
  2278. }
  2279. }
  2280.  
  2281. if (output) do_output(ans);
  2282. return 0;
  2283.  
  2284. /*
  2285. { // Keep only songs for dancers with boredom one
  2286. const int NDANCERS = L.size()-1, NSONGS = L[0].size()-1;
  2287. cerr << "\t PREV NDANCERS " << L.size()-1 << " NSONGS " << L[0].size()-1 << endl;
  2288. vector<bool> keep(NSONGS,1);
  2289.  
  2290. vector<int> numb(NDANCERS,0);
  2291. for (int i=0;i<NDANCERS;++i) ++numb[L[i][NSONGS]];
  2292.  
  2293. for (int j=0;j<NSONGS;++j) {
  2294. for (int i=0;i<NDANCERS;++i) if (L[i][NSONGS]==1 && !L[i][j]) {
  2295. keep[j] = 0;
  2296. break;
  2297. }
  2298. }
  2299.  
  2300. int totb = 0;
  2301. const int CONS = 5;
  2302. for (int i=0;i<min(NDANCERS,CONS+1);++i) totb += numb[i];
  2303.  
  2304. for (int j=0;j<NSONGS;++j) {
  2305. int cnt = 0;
  2306. for (int i=0;i<NDANCERS;++i) if (L[i][NSONGS]<=5 && L[i][j]) {
  2307. ++cnt;
  2308. }
  2309. if (cnt>0 && cnt>=totb/2) {
  2310. keep[j] = 1;
  2311. }
  2312. }
  2313.  
  2314. L = transpose(L);
  2315. vvi newL;
  2316. for (int i=0;i<NSONGS;++i) if (keep[i]) newL.push_back(L[i]);
  2317. newL.push_back(L.back());
  2318. newL = transpose(newL);
  2319. L = newL;
  2320. cerr << "\t NOW NDANCERS " << L.size()-1 << " NSONGS " << L[0].size()-1 << endl;
  2321.  
  2322. if (NSONGS == L[0].size()-1) {
  2323. if (output) do_output(p0.second);
  2324. return 0;
  2325. }
  2326. }
  2327. */
  2328.  
  2329.  
  2330.  
  2331. //vvi oldL = L;
  2332.  
  2333. /*
  2334. // Doesn't seem to have any effect
  2335. L = oldL;
  2336.  
  2337. int p0s = L.size(), p1s = L[0].size();
  2338. for (int r=20,its=0;its<1;++r,++its) {
  2339. L = remove_boredom_bound(L, r);
  2340. if (L.size()-1 <= BEST_SOL || L[0].size()<=1) break;
  2341.  
  2342. if (p0s == L.size() && p1s == L[0].size()) continue;
  2343. p0s = L.size(), p1s = L[0].size();
  2344.  
  2345. int PREV_SOL = BEST_SOL;
  2346. pair<int,vector<int> > p2 = realsolve(L);
  2347. #ifndef ONLINE_JUDGE
  2348. cerr << "\t2: TRYING HERE " << L.size()-1 << " AND NSONGS " << L[0].size() - 1 << " GET " << BEST_SOL << " PREV " << PREV_SOL << endl;
  2349. #endif
  2350. if (p2.first > PREV_SOL) {
  2351. #ifdef ONLINE_JUDGE
  2352. assert(0);
  2353. #endif
  2354. ans = p2.second;
  2355. }
  2356. }
  2357. */
  2358.  
  2359. if (output) do_output(ans);
  2360. return 0;
  2361. }
  2362.  
  2363. // LOCAL TESTS
  2364. //{{{
  2365. #ifdef LOCAL
  2366. void run_tests() {
  2367.  
  2368. int sol = 0;
  2369. int opt_solve = 0;
  2370. int tot = 0;
  2371.  
  2372. string curdir = "testdata";
  2373. DIR* dir = opendir(curdir.c_str());
  2374. for (dirent* de; de = readdir(dir);) {
  2375. if (!strcmp(de->d_name,".svn")) continue;
  2376.  
  2377. if (de->d_type == DT_DIR) { // recurse into this directory
  2378. continue;
  2379. }
  2380. else if (de->d_type == DT_REG) {
  2381. string name = curdir + "/" + de->d_name;
  2382. if (name.length()>=3 && name.substr(int(name.length())-4)==".txt") {
  2383. ifstream fin(name.c_str());
  2384. bufsz = 0;
  2385. for (string x;getline(fin,x);) {
  2386. for (int j=0;j<x.length();++j) {
  2387. buf[bufsz++] = x[j];
  2388. }
  2389. buf[bufsz++] = '\n';
  2390. }
  2391. start = buf;
  2392.  
  2393. int bestsolved = solve(false);
  2394.  
  2395. cerr << "Case " << de->d_name << "\tsolved opt: " << bestsolved << "\tsolution " << BEST_SOL << " SIZE " << REAL_ANS.size() << endl;
  2396.  
  2397. opt_solve += bestsolved;
  2398. sol += BEST_SOL;
  2399. ++tot;
  2400. }
  2401. }
  2402. }
  2403. cerr << endl;
  2404. cerr << "STATS " << endl;
  2405. cerr << "SCORE : " << sol << endl;
  2406. cerr << "OPT SOL : " << opt_solve << endl;
  2407. cerr << "NUM CAS : " << tot << endl;
  2408. closedir(dir);
  2409. }
  2410. #endif
  2411. //}}}
  2412. // END LOCAL TESTS
  2413.  
  2414. int main(int argc, char** argv) {
  2415. if (argc == 2 && !strcmp(argv[1], "tests")) {
  2416. #ifdef LOCAL
  2417. cerr << "RUNNING TESTS " << endl;
  2418. run_tests();
  2419. return 0;
  2420. #endif
  2421. }
  2422. take_input();
  2423. solve(true);
  2424. }


Comments

  • Login or Register to post a comment.

CodeChef is a non-commercial competitive programming community
  • About CodeChef
  • About Directi
  • CEO's Corner
  • C-Programming
  • Programming Languages
  • Contact Us
© 2009 Directi Group. All Rights Reserved. CodeChef uses SPOJ © by Sphere Research Labs
In order to report copyright violations of any kind, send in an email to copyright@codechef.com
CodeChef a product of Directi
The time now is:
CodeChef - A Platform for Aspiring Programmers

CodeChef was created as a platform to help programmers make it big in the world of computer programming. At CodeChef we work hard to revive the geek in you by hosting programming contests on a monthly basis. We also aim to have training sessions and events related to online programming for programmers around the world. Apart from providing a platform for programming competitions, CodeChef also has various tutorials and forum discussions to help those who are new to the world of computer programming.

Practice Section - A Place to hone your 'Computer Programming Skills'

Try your hand at one of our many practice problems and submit your solution in a language of your choice. Our judge accepts solutions in over 35+ programming languages. Online programming was never this much fun! Receive points, and move up through the CodeChef ranks. Use our practice section to better prepare yourself for the multiple programming competitions that take place through-out the month on CodeChef.

Compete - Monthly Programming Contests and Cook-offs

Here is where you can show off your computer programming skills. Take part in our 10 day long monthly programming contests and the shorter format Cook-off programming contests. Put yourself up for recognition and win great prizes. Prizes worth up to Rs.20,000 and $700 are up for grabs every month along with lots more CodeChef goodies.

Discuss

Are you new to computer programming? Do you need help with algorithms? Then be part of CodeChefs Forums and interact with all our programmers love helping out other programmers and share their ideas.

CodeChef Community

As part of our Educational initiative, we give institutes the opportunity to associate with CodeChef in the form of Campus Chapters. Hosting online programming competitions is not the only feature on CodeChef. Be a part of the CodeChef community through CodeChef meetups and techtalks. You can also host a programming contest for your institute on CodeChef and be a guest author on our blog.

Domain Name Registration, Web hosting, and Website Design provided by BigRock.com