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
    • All Contests
    • June Long 2012
    • May Cook-Off
    • May Long 2012
  • DISCUSS
    • Forums
    • Blog
    • Wiki
    • Facebook
    • Twitter
  • COMMUNITY
    • CodeChef Meetups
    • Campus Chapters
    • Host your Contest
    • User Groups
    • CodeChef TechTalks
    • All Educational Initiatives
  • HELP
    • Frequently Asked Questions
    • FAQ for problem setters
    • Problem Setting
    • Tutorials
    • Long Contest Ranks
    • Short Contest Ranks
    • Event Calendar
  • ABOUT
    • About CodeChef
    • Team CodeChef
    • Press Room
    • CodeChef Financials
    • CodeChef Sponsorships
    • CEO's Corner
    • Contact Us
    • About Directi
Home » Compete » July 2009 (Contest IV) » Lights Off, Revisited!
0
Your rating: None

CodeChef submission 53306 (C++ 4.0.0-8)

CodeChef submission 53306 (C++ 4.0.0-8) plaintext list. Status: TLE, problem EX, contest JULY09. By gmark (Mark Greve), 2009-07-10 15:18:59.
  1. // Lights Off, Revisited!
  2. // Source: CodeChef July 2009 Challenge
  3. // CodeChef ID: EX
  4. // Date: 06-07-2009
  5. // Author: Mark Greve
  6. // Keywords: DP
  7. // Status: AC
  8. // Difficulty: hard
  9. // Complexity:
  10. // Comments:
  11. // This solution uses only E and W moves and then uses DP to compute the best
  12. // solution row-by-row (trying the best combination). Also, we attempt to
  13. // transpose the matrix and try again. This solution also uses a more advanced DP approach,
  14. // which is unfortunately a bit slower.
  15. //
  16. // This is the best solution so far.
  17. // Now with timing code...
  18. //
  19. // Three criteria:
  20. // 1. Minimum penalty
  21. // 2. Minimum number of moves
  22. // 3. Rows differing as much as possible
  23.  
  24. #include <algorithm>
  25. #include <bitset>
  26. #include <cassert>
  27. #include <cctype>
  28. #include <cmath>
  29. #include <cstdio>
  30. #include <cstdlib>
  31. #include <cstring>
  32. #include <ctime>
  33. #include <deque>
  34. #include <functional>
  35. #include <iomanip>
  36. #include <iostream>
  37. #include <list>
  38. #include <map>
  39. #include <numeric>
  40. #include <queue>
  41. #include <set>
  42. #include <sstream>
  43. #include <stack>
  44. #include <string>
  45. #include <utility>
  46. #include <vector>
  47. using namespace std;
  48.  
  49. // TIMING CODE
  50. #include <sys/time.h>
  51. #include <sys/resource.h>
  52. #include <stdint.h>
  53. #include <time.h>
  54.  
  55. typedef uint_fast64_t test_realtime_t;
  56.  
  57. inline void get_test_realtime(test_realtime_t& a) {
  58. struct timeval tv;
  59. gettimeofday(&tv, NULL);
  60. a = tv.tv_sec;
  61. a *= 1000*1000;
  62. a += tv.tv_usec;
  63. }
  64.  
  65. inline uint_fast64_t testRealtimeDiff(const test_realtime_t a, const test_realtime_t b) {
  66. return b - a;
  67. }
  68. // END TIMING CODE
  69.  
  70. #define MP make_pair
  71. typedef pair<int,int> pii;
  72. typedef vector<pair<pii,char> > vsol;
  73.  
  74. const int MAX=1005;
  75. int B[MAX][MAX];
  76. int C[MAX][MAX];
  77. int n;
  78. const int INF=1<<29;
  79.  
  80. // UTILITY FUNCTIONS
  81. void show_board() {
  82. printf("N: %d\n", n);
  83. for (int i=0;i<n;++i) {
  84. for (int j=0;j<n;++j) printf("%d", B[i][j]);
  85. printf("\n");
  86. }
  87. }
  88. char transpose_dir(char c) {
  89. if (c=='E') return 'S';
  90. if (c=='W') return 'N';
  91. if (c=='S') return 'E';
  92. if (c=='N') return 'W';
  93. }
  94.  
  95. void perform(int y, int x, char d) {
  96. if (d=='N') { while (y>=0) B[y][x] = !B[y][x], --y; }
  97. if (d=='S') { while (y<n) B[y][x] = !B[y][x], ++y; }
  98. if (d=='E') { while (x<n) B[y][x] = !B[y][x], ++x; }
  99. if (d=='W') { while (x>=0) B[y][x] = !B[y][x], --x; }
  100. }
  101. void transpose() {
  102. for (int i=0;i<n;++i)
  103. for (int j=0;j<i;++j)
  104. swap(B[i][j],B[j][i]);
  105. }
  106. // Count the number of ones on the board.
  107. int countones() {
  108. int cnt = 0;
  109. for (int i=0;i<n;++i)
  110. for (int j=0;j<n;++j)
  111. cnt += B[i][j];
  112. return cnt;
  113. }
  114. void copy_back() {
  115. for (int i=0;i<n;++i)
  116. for (int j=0;j<n;++j)
  117. B[i][j] = C[i][j];
  118. }
  119. void show_sol(const vsol& moves) {
  120. printf("%d\n", moves.size());
  121. for (int i=0;i<moves.size();++i)
  122. printf("%d %d %c\n", moves[i].first.first, moves[i].first.second, moves[i].second);
  123. }
  124. // Copy only the unique moves over
  125. vsol fixmoves(vsol moves) {
  126. sort(moves.begin(),moves.end());
  127. vsol moves2;
  128. int cnt = 0;
  129. for (int i=0;i<moves.size();++i) {
  130. if (i==0 || moves[i] == moves[i-1]) ++cnt;
  131. else {
  132. if (cnt%2==1) moves2.push_back(moves[i-1]);
  133. cnt = 1;
  134. }
  135. }
  136. if (cnt%2==1) moves2.push_back(moves.back());
  137. return moves2;
  138. }
  139. // NESW
  140. const int dy[]={-1,0,1,0};
  141. const int dx[]={ 0,1,0,-1};
  142. char dir2c(int x) {
  143. switch(x) {
  144. case 0: return 'N';
  145. case 1: return 'E';
  146. case 2: return 'S';
  147. case 3: return 'W';
  148. }
  149. }
  150. // END UTILITY FUNCTIONS
  151.  
  152.  
  153. // SMALL CASE SOLVER
  154. const int MAXD=3;
  155. int dpsmall[MAXD][MAXD][1<<(MAXD*MAXD)];
  156. int choicesmall[MAXD][MAXD][1<<(MAXD*MAXD)];
  157. int newns[MAXD][MAXD][1<<(MAXD*MAXD)];
  158.  
  159. template<class T> inline int BITCNT(T x){int r=0;while(x){r++;x&=x-1;}return r;}
  160.  
  161. int go_small(int y, int x, int s) {
  162. if (y==MAXD) return BITCNT(s);
  163. if (x==MAXD) return go_small(y+1,0,s);
  164. int& ref = dpsmall[y][x][s];
  165. if (ref!=-1) return ref;
  166. int& ch = choicesmall[y][x][s];
  167. int& news = newns[y][x][s];
  168. ch = 0;
  169. news = s;
  170. ref = go_small(y,x+1,s);
  171. for (int k=0;k<4;++k) {
  172. int ns = s;
  173. int ny = y;
  174. int nx = x;
  175. while (0 <= nx && nx < MAXD && 0 <= ny && ny < MAXD) {
  176. ns ^= (1<<(ny*MAXD + nx));
  177. ny += dy[k];
  178. nx += dx[k];
  179. }
  180. int next = 2 + go_small(y,x+1,ns);
  181. if (next<ref) {
  182. ch = k+1;
  183. ref = next;
  184. news = ns;
  185. }
  186. }
  187. return ref;
  188. }
  189.  
  190. int get_moves_small(int y, int x, int oy, int ox, int s, vsol& moves, bool transposed) {
  191. if (y==MAXD) return s;
  192. if (x==MAXD) return get_moves_small(y+1,0,oy,ox,s,moves,transposed);
  193. int ch = choicesmall[y][x][s];
  194. int ns = newns[y][x][s];
  195.  
  196. if (ch==0) return get_moves_small(y,x+1,oy,ox,ns,moves,transposed);
  197. --ch;
  198. if (!transposed) moves.push_back(MP(MP(oy + y,ox + x), dir2c(ch)));
  199. else moves.push_back(MP(MP(ox + x, oy + y),transpose_dir(dir2c(ch))));
  200. // Might be invalid
  201. if (ch==0) moves.push_back(MP(MP(oy - 1 , ox+x ), dir2c(ch))); // N
  202. else if (ch==1) moves.push_back(MP(MP(oy+y , ox+MAXD), dir2c(ch))); // E
  203. else if (ch==2) moves.push_back(MP(MP(oy + MAXD, ox+x ), dir2c(ch))); // S
  204. else if (ch==3) moves.push_back(MP(MP(oy+y , ox-1 ), dir2c(ch))); // W
  205. if (transposed) {
  206. swap(moves.back().first.first, moves.back().first.second);
  207. moves.back().second = transpose_dir(moves.back().second);
  208. }
  209.  
  210. // So prune it
  211. if (
  212. moves.back().first.first >= n || moves.back().first.first < 0 ||
  213. moves.back().first.second >= n || moves.back().first.second < 0
  214. )
  215. moves.pop_back();
  216.  
  217.  
  218. return get_moves_small(y,x+1,oy,ox, ns, moves, transposed);
  219. }
  220.  
  221. // Run over then entire board and optimize all MAXDxMAXD squares
  222. void do_small_case_solve(vsol& moves, bool transposed) {
  223. for (int y=0;y+MAXD-1<n;++y) {
  224. for (int x=0;x+MAXD-1<n;++x) {
  225.  
  226. int s = 0;
  227. for (int _dy=0;_dy<MAXD;++_dy) {
  228. for (int _dx=0;_dx<MAXD;++_dx) {
  229. if (B[y+_dy][x+_dx])
  230. s |= (1<<(MAXD*(_dy) + _dx));
  231. }
  232. }
  233.  
  234. go_small(0,0,s);
  235. int ns = get_moves_small(0,0,y,x,s,moves,transposed);
  236. for (int _dy=0;_dy<MAXD;++_dy)
  237. for (int _dx=0;_dx<MAXD;++_dx)
  238. B[y+_dy][x+_dx] = bool(ns&(1<<( MAXD*(_dy) + _dx)));
  239. }
  240. }
  241. }
  242.  
  243. // END SMALL CASE SOLVER
  244.  
  245. vsol tmpmoves; // Stores the temporary moves for any get_moves method
  246.  
  247. // DP to compute the minimum possible penalty for a row (using east moves)
  248. int dp_east[MAX][2];
  249. int choice_east[MAX][2];
  250. int min_cost_row_east(int r, int at, int flip) {
  251. if (at>=n) return 0;
  252. int& ref = dp_east[at][flip];
  253. if (ref!=-1) return ref;
  254. int state = (B[r][at] ^ flip);
  255. int& ch = choice_east[at][flip];
  256. ch = 0;
  257.  
  258. // Try doing nothing.
  259. ref = (state<<20) + min_cost_row_east(r, at+1, flip) + (r>0 ? B[r-1][at]!=state : 0);
  260.  
  261. // Try flipping east here.
  262. int other = (1<<1) + ((1 + (!state))<<20) + min_cost_row_east(r,at+1,!flip) + (r>0 ? B[r-1][at]!=(!state) : 0);
  263.  
  264. if (other<=ref) { // Prefer the flip or not ? (<= vs <)
  265. ref = other;
  266. ch = 1;
  267. }
  268. return ref;
  269. }
  270.  
  271. void get_moves_east(int r, int at=0, bool flip=0, bool transposed=0) {
  272. if (at>=n) return;
  273. if (choice_east[at][flip]==0) return get_moves_east(r, at+1,flip,transposed);
  274. if (!transposed) tmpmoves.push_back(MP(MP(r,at),'E'));
  275. else tmpmoves.push_back(MP(MP(at,r),'S'));
  276. get_moves_east(r, at+1, !flip, transposed);
  277. }
  278.  
  279. int dp_west[MAX][2];
  280. int choice_west[MAX][2];
  281.  
  282.  
  283. // DP to compute the minimum possible penalty for a row (using west moves)
  284. int min_cost_row_west(int r, int at, int flip) {
  285. if (at<0) return 0;
  286. int& ref = dp_west[at][flip];
  287. if (ref!=-1) return ref;
  288. int state = (B[r][at] ^ flip);
  289. int& ch = choice_west[at][flip];
  290. ch = 0;
  291. // Try doing nothing.
  292. ref = (state<<20) + min_cost_row_west(r, at-1, flip) + (r>0 ? B[r-1][at]!=state : 0);
  293.  
  294. // Try flipping west here.
  295. int other = (1<<1) + ((1 + (!state))<<20) + min_cost_row_west(r,at-1,!flip) + (r>0 ? B[r-1][at]!=(!state) : 0);
  296.  
  297. if (other<=ref) { // Prefer the flip or not ? (<= vs <)
  298. ref = other;
  299. ch = 1;
  300. }
  301. return ref;
  302. }
  303.  
  304. void get_moves_west(int r, int at=n-1, bool flip=0, bool transposed=0) {
  305. if (at<0) return;
  306. if (choice_west[at][flip]==0) return get_moves_west(r, at-1,flip, transposed);
  307. if (!transposed) tmpmoves.push_back(MP(MP(r,at),'W'));
  308. else tmpmoves.push_back(MP(MP(at,r),'N'));
  309. get_moves_west(r, at-1, !flip, transposed);
  310. }
  311.  
  312. // Solve a row in O(n^2) using WEST as a prefix and EAST as a suffix
  313. // Insert the moves into moves and simulate the moves
  314. void solve_row_naive(int y, vsol& moves, bool transposed, bool simulate=1) {
  315. // Clear the DP tables
  316. for (int x=0;x<n;++x) dp_east[x][0]=dp_east[x][1]=-1;
  317. for (int x=0;x<n;++x) dp_west[x][0]=dp_west[x][1]=-1;
  318.  
  319. // Find the best combination
  320. int minv = -1, idx = -1;
  321. for (int pre=-1;pre<n;++pre) {
  322. int cost = min_cost_row_west(y,pre,0) + min_cost_row_east(y,pre+1,0);
  323. if (minv==-1 || (cost<minv)) {
  324. minv = cost;
  325. idx = pre;
  326. }
  327. }
  328. if (simulate) {
  329. tmpmoves.clear();
  330. get_moves_west(y,idx,0,transposed);
  331.  
  332. // Simulate the WEST moves
  333. bool flip = 0;
  334. int at = idx;
  335. for (int i=0;i<tmpmoves.size();++i) {
  336. int x = (!transposed ? tmpmoves[i].first.second : tmpmoves[i].first.first);
  337. while (at>x) B[y][at] ^= flip, --at;
  338. flip = !flip;
  339. }
  340. while (at>=0) B[y][at] ^= flip, --at;
  341.  
  342. int bef = tmpmoves.size();
  343. get_moves_east(y,idx+1,0,transposed);
  344.  
  345. // Simulate the EAST moves
  346. at = idx+1;
  347. flip = 0;
  348. for (int i=bef;i<tmpmoves.size();++i) {
  349. int x = (!transposed ? tmpmoves[i].first.second : tmpmoves[i].first.first);
  350. while (at<x) B[y][at] ^= flip, ++at;
  351. flip = !flip;
  352. }
  353. while (at<n) B[y][at] ^= flip, ++at;
  354.  
  355. moves.insert(moves.end(), tmpmoves.begin(),tmpmoves.end());
  356. }
  357. }
  358.  
  359. test_realtime_t START_TIME; // global start time
  360.  
  361. // Solve, transpose and call recursively to solve again
  362. // using the more naive DP approach (but faster, i.e. O(n^2))
  363. void naivesolver(int bound, vsol& moves, bool transposed, int TIMEBOUND) {
  364. int runs = 0;
  365. while (runs<=bound) {
  366.  
  367. for (int y=0;y<n;++y) {
  368. if (y%100==0) {
  369. test_realtime_t a;
  370. get_test_realtime(a);
  371. if (testRealtimeDiff(START_TIME,a)>=TIMEBOUND) return;
  372. }
  373. solve_row_naive(y,moves,transposed);
  374. }
  375.  
  376. transpose();
  377. transposed = !transposed;
  378. ++runs;
  379. }
  380. }
  381.  
  382. int solve(vsol& moves) {
  383.  
  384. // Transposed solution
  385. vsol sol0;
  386. //naivesolver(INF,sol0,0,4300000);
  387. //sol0 = fixmoves(sol0);
  388. int cost0 = moves.size() + countones() + sol0.size(); // Compute the real cost.
  389.  
  390. // Not transposed
  391. copy_back();
  392. transpose();
  393. vsol sol1;
  394. naivesolver(INF,sol1,1,4500000);
  395. sol1 = fixmoves(sol1);
  396. int cost1 = moves.size() + countones() + sol1.size();
  397.  
  398. if (cost0<cost1) moves.insert(moves.end(),sol0.begin(),sol0.end());
  399. else moves.insert(moves.end(),sol1.begin(),sol1.end());
  400. return min(cost0,cost1);
  401. }
  402.  
  403. // FAST IO
  404. char *start;
  405. const int MAXBUF=30000000;
  406. char buf[MAXBUF];
  407. void skip() {
  408. while (*start != 0 && !('0' <= *start && *start <= '9')) start++;
  409. }
  410. void GETNUM(int& n){
  411. skip();
  412. n=0;
  413. while ('0' <= *start && *start <= '9') {
  414. n = n*10 + *start-'0', ++start;
  415. }
  416. }
  417.  
  418. // END FAST IO
  419.  
  420. void take_input() { // Take input using fast I/O
  421. int sz=fread(buf, sizeof(char), MAXBUF, stdin);
  422. buf[sz]=0;
  423. start=buf;
  424. GETNUM(n);
  425.  
  426. for (int i=0;i<n;++i) {
  427. for (int j=0;j<n;++j) {
  428. GETNUM(B[i][j]);
  429. C[i][j] = B[i][j];
  430. }
  431. }
  432. }
  433.  
  434. int main() {
  435. get_test_realtime(START_TIME);
  436. //memset(dpsmall,-1,sizeof dpsmall);
  437. take_input();
  438. vsol sol0;
  439. int cost0 = solve(sol0);
  440. show_sol(sol0);
  441. }


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 algorithms, computer programming and programming contests. At CodeChef we work hard to revive the geek in you by hosting a programming contest at the start of the month and another smaller programming challenge in the middle of the month. We also aim to have training sessions and discussions related to algorithms, binary search, technicalities like array size and the likes. Apart from providing a platform for programming competitions, CodeChef also has various algorithm 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 programming contest judge accepts solutions in over 35+ programming languages. Preparing for coding contests were 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 challenges 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 coding contest and the shorter format Cook-off coding contest. Put yourself up for recognition and win great prizes. Our programming contests have prizes worth up to Rs.20,000 and $700lots more CodeChef goodies up for grabs.

Discuss

Are you new to computer programming? Do you need help with algorithms? Then be a part of CodeChef's Forums and interact with all our programmers - they love helping out other programmers and sharing their ideas. Have discussions around binary search, array size, branch-and-bound, Dijkstra's algorithm, Encryption algorithm and more by visiting the CodeChef Forums and Wiki section.

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. You can also host a coding contest for your institute on CodeChef, organize an algorithm event and be a guest author on our blog.

Go For Gold

The Go for Gold Initiative was launched about a year after CodeChef was incepted, to help prepare Indian students for the ACM ICPC World Finals competition. In the run up to the ACM ICPC competition, the Go for Gold initiative uses CodeChef as a platform to train students for the ACM ICPC competition via multiple warm up contests. As an added incentive the Go for Gold initiative is also offering over Rs.8 lacs to the Indian team that beats the 29th position at the ACM ICPC world finals. Find out more about the Go for Gold and the ACM ICPC competition here.

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