Назад к лучшим решениям Status: AC, problem ZRIS, contest ZEL06. By werewolf (Werewolf), 2006-02-25 06:02:26.
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <search.h>
  5. #include <time.h>
  6. typedef struct _WIDTHCOUNT
  7. {
  8. unsigned short width;
  9. unsigned short count;
  10. }WIDTHCOUNT, *PWIDTHCOUNT;
  11. #define MAXWIDTH 1000
  12. WIDTHCOUNT Rectangles[MAXWIDTH+1][MAXWIDTH+1];
  13. unsigned short SumElements[MAXWIDTH +1];
  14. unsigned short BestSum[MAXWIDTH +3];
  15. unsigned int Square[MAXWIDTH+1][MAXWIDTH+1];
  16. unsigned int nUsedElements;
  17. unsigned int nCountRect;
  18.  
  19.  
  20.  
  21. int __inline comparewidth( const void *arg1, const void *arg2 )
  22. {
  23. return ((PWIDTHCOUNT)arg1)->width == ((PWIDTHCOUNT)arg2)->width?0:((PWIDTHCOUNT)arg1)->width < ((PWIDTHCOUNT)arg2)->width?-1:1;
  24. }
  25. int __inline AddRectangle(unsigned short size1, unsigned short size2, unsigned short count)
  26. {
  27. WIDTHCOUNT wc, *pwc, *pwc1;
  28. unsigned int num;
  29. wc.width = size1;
  30. num = Rectangles[0][0].count;
  31. pwc = lfind(&wc, &Rectangles[1], &num, sizeof(Rectangles[0]), comparewidth);
  32. if(!pwc)
  33. {
  34. Rectangles[0][0].count++;
  35. Rectangles[Rectangles[0][0].count][0].width = size1;
  36. Rectangles[Rectangles[0][0].count][0].count = 1;
  37. Rectangles[Rectangles[0][0].count][1].width = size2;
  38. Rectangles[Rectangles[0][0].count][1].count = count;
  39. }else
  40. {
  41. wc.width = size2;
  42. num = pwc->count;
  43. pwc1 = lfind(&wc, &pwc[1], &num, sizeof(Rectangles[0][0]), comparewidth);
  44. if(!pwc1)
  45. {
  46. pwc->count ++;
  47. pwc[pwc->count].width = size2;
  48. pwc[pwc->count].count = count;
  49. }else
  50. {
  51. pwc1->count += count;
  52. }
  53. }
  54. if(size2 == size1)
  55. return 1;
  56. wc.width = size2;
  57. num = Rectangles[0][0].count;
  58. pwc = lfind(&wc, &Rectangles[1], &num, sizeof(Rectangles[0]), comparewidth);
  59. if(!pwc)
  60. {
  61. Rectangles[0][0].count++;
  62. Rectangles[Rectangles[0][0].count][0].width = size2;
  63. Rectangles[Rectangles[0][0].count][0].count = 1;
  64. Rectangles[Rectangles[0][0].count][1].width = size1;
  65. Rectangles[Rectangles[0][0].count][1].count = count;
  66. }else
  67. {
  68. wc.width = size1;
  69. num = pwc->count;
  70. pwc1 = lfind(&wc, &pwc[1], &num, sizeof(Rectangles[0][0]), comparewidth);
  71. if(!pwc1)
  72. {
  73. pwc->count ++;
  74. pwc[pwc->count].width = size1;
  75. pwc[pwc->count].count = count;
  76. }else
  77. {
  78. pwc1->count += count;
  79. }
  80. }
  81. /*
  82. int i, j;
  83.  
  84. for(i = 1; i<=Rectangles[0][0].count;i++)
  85. {
  86. if(Rectangles[i][0].width == size1)
  87. break;
  88. }
  89. if(i == Rectangles[0][0].count+1)
  90. {
  91. Rectangles[i][0].width = size1;
  92. Rectangles[0][0].count++;
  93. }
  94.  
  95. for(j = 1; j<=Rectangles[i][0].count;j++)
  96. {
  97. if(Rectangles[i][j].width == size2)
  98. break;
  99. }
  100. if(j == Rectangles[i][0].count+1)
  101. {
  102. Rectangles[i][j].width = size2;
  103. Rectangles[i][j].count = count;
  104. Rectangles[i][0].count++;
  105. }else
  106. Rectangles[i][j].count += count;
  107.  
  108. if(size2 == size1)
  109. return 1;
  110.  
  111. for(i = 1; i<=Rectangles[0][0].count;i++)
  112. {
  113. if(Rectangles[i][0].width == size2)
  114. break;
  115. }
  116. if(i == Rectangles[0][0].count+1)
  117. {
  118. Rectangles[i][0].width = size2;
  119. Rectangles[0][0].count++;
  120. }
  121.  
  122. for(j = 1; j<=Rectangles[i][0].count;j++)
  123. {
  124. if(Rectangles[i][j].width == size1)
  125. break;
  126. }
  127.  
  128. if(j == Rectangles[i][0].count+1)
  129. {
  130. Rectangles[i][j].width = size1;
  131. Rectangles[i][j].count = count;
  132. Rectangles[i][0].count++;
  133. }else
  134. Rectangles[i][j].count += count;
  135. */
  136. return 1;
  137. }
  138. int SortRectangles()
  139. {
  140. int i;
  141. qsort(&Rectangles[1], Rectangles[0][0].count, sizeof(Rectangles[1]), comparewidth);
  142. for(i = 1; i<Rectangles[0][0].count+1;i++)
  143. {
  144. qsort(&Rectangles[i][1], Rectangles[i][0].count, sizeof(Rectangles[0][0]), comparewidth);
  145. }
  146. return 1;
  147. }
  148. void __inline DeleteArray(int pos)
  149. {
  150. memmove(&Rectangles[pos], &Rectangles[pos+1], (Rectangles[0][0].count-pos)*sizeof(Rectangles[0]));
  151. Rectangles[0][0].count--;
  152.  
  153. }
  154. void __inline DeleteElement(int pos1, int pos2)
  155. {
  156. if(!--Rectangles[pos1][pos2].count)
  157. {
  158. memmove(&Rectangles[pos1][pos2], &Rectangles[pos1][pos2+1], (Rectangles[pos1][0].count-pos2)*sizeof(Rectangles[0][0]));
  159. if(!--Rectangles[pos1][0].count)
  160. DeleteArray(pos1);
  161. }
  162. }
  163. int __inline FindElement(unsigned short width, int HeightPos, int MaxWidthPos)
  164. {
  165. WIDTHCOUNT wc, *pwc;
  166. if(Rectangles[HeightPos][MaxWidthPos].width < width)
  167. return 0;
  168. wc.width = width;
  169. if((pwc = (PWIDTHCOUNT)bsearch(&wc, &Rectangles[HeightPos][1], MaxWidthPos, sizeof(WIDTHCOUNT), comparewidth)) &&
  170. pwc->count)
  171. return ((unsigned int)pwc - (unsigned int)&Rectangles[HeightPos][0])/sizeof(WIDTHCOUNT);
  172. else
  173. return 0;
  174. }
  175. int __inline FindArray(unsigned short height, int MaxHeightPos)
  176. {
  177. WIDTHCOUNT wc, *pwc;
  178. if(Rectangles[MaxHeightPos][0].width < height)
  179. return 0;
  180.  
  181. wc.width = height;
  182. if((pwc = (PWIDTHCOUNT)bsearch(&wc, &Rectangles[1], MaxHeightPos, sizeof(Rectangles[0]), comparewidth)) &&
  183. pwc->count)
  184. return ((unsigned int)pwc - (unsigned int)&Rectangles[0])/sizeof(Rectangles[0]);
  185. else
  186. return 0;
  187. }
  188. int __inline UpdateBestSum(unsigned short SumPart, int count, int height)
  189. {
  190. if(BestSum[0]>SumPart || (BestSum[0]==SumPart && BestSum[1] > count))
  191. {
  192.  
  193. memcpy(BestSum+3, SumElements, count*sizeof(SumElements[0]));
  194. BestSum[0] = SumPart;
  195. BestSum[1] = count;
  196. BestSum[2] = height;
  197. return 1;
  198. }
  199. return 0;
  200. }
  201. unsigned short CanCompleteSum(unsigned short pos, unsigned short sum, int maxpos)
  202. {
  203. int i, isless = 1, ismore = 0, fullsum = 0;
  204. for(i = 1;i<=maxpos;i++)
  205. {
  206. if(!Rectangles[pos][i].count)
  207. continue;
  208. if(isless && Rectangles[pos][i].width<=sum)
  209. isless = 0;
  210.  
  211. fullsum += Rectangles[pos][i].width*Rectangles[pos][i].count;
  212.  
  213. }
  214. return isless?0:fullsum>=sum?sum:fullsum;
  215. }
  216.  
  217. int FindSum(int MaxItems, unsigned short NeedSum, unsigned short HeightPos, unsigned short MaxWidthPos, int ItemNumber)
  218. {
  219. int tmp, finded = 0;
  220. int SumPart, i;
  221.  
  222. if(!MaxWidthPos)
  223. return -1;
  224.  
  225. if(MaxItems == 0)
  226. return 0;
  227.  
  228. if(FindElement(NeedSum, HeightPos, MaxWidthPos))
  229. {
  230. SumElements[ItemNumber] = NeedSum;
  231. UpdateBestSum(0, ItemNumber+1, Rectangles[HeightPos][0].width);
  232. return 1;
  233. }
  234.  
  235. for(i = MaxWidthPos;i>0;i--)
  236. {
  237. SumPart = NeedSum-Rectangles[HeightPos][i].width;
  238. if(!Rectangles[HeightPos][i].count || SumPart <= 0)
  239. continue;
  240.  
  241. tmp = Rectangles[HeightPos][i].width;
  242. Rectangles[HeightPos][i].count--;
  243. SumElements[ItemNumber] = tmp;
  244. UpdateBestSum(SumPart, ItemNumber+1, Rectangles[HeightPos][0].width);
  245.  
  246. finded = FindSum(MaxItems - 1, SumPart, HeightPos, Rectangles[HeightPos][i].count?i:i-1, ItemNumber+1);
  247. Rectangles[HeightPos][i].count++;
  248.  
  249. if(finded)
  250. return finded;
  251. }
  252.  
  253. return 0;
  254. }
  255. void DeleteItem(unsigned short width, unsigned short height)
  256. {
  257. unsigned pos1, pos2;
  258. pos1 = FindArray(height, Rectangles[0][0].count);
  259. if(pos1)
  260. {
  261. pos2 = FindElement(width, pos1, Rectangles[pos1][0].count);
  262. if(pos2)
  263. {
  264. DeleteElement(pos1, pos2);
  265. }
  266. }
  267. if(width == height)
  268. return;
  269. pos1 = FindArray(width, Rectangles[0][0].count);
  270. if(pos1)
  271. {
  272. pos2 = FindElement(height, pos1, Rectangles[pos1][0].count);
  273. if(pos2)
  274. {
  275. DeleteElement(pos1, pos2);
  276. }
  277. }
  278. }
  279.  
  280. int FindNextPlace(unsigned short xmax, unsigned short ymax, unsigned short * px, unsigned short *py , unsigned short * psx, unsigned short * plsy, unsigned short * prsy)
  281. {
  282. short x = xmax, y = 0, dx = 0, dy = 0, sx = 0, sy = 0, rsy = 0, lsy = 0;
  283. short curx = xmax, cury = 0, cursx = 0, curlsy = 0, currsy = 0;
  284.  
  285. if(!Square[x-1][y])
  286. {
  287. x--;
  288. dx = -1;
  289. curx = x;
  290. cury = y;
  291. cursx = 1;
  292. }else
  293. {
  294. dy = 1;
  295. }
  296. *py = ymax;
  297. *px = 0;
  298. *psx = 0;
  299. while(x > 0)
  300. {
  301. //step down
  302. if(dy !=1 && y>0 && !Square[x][y-1])
  303. {
  304. if(dx == -1)
  305. currsy = 0;
  306. // if(dy == -1)
  307. currsy++;
  308. cursx = 1;
  309. dx = 0;
  310. dy = -1;
  311. }else
  312. //step left
  313. if(x>0 && !Square[x-1][y])
  314. {
  315. if(dx == -1)
  316. cursx;
  317. else if(dy == -1)
  318. {
  319. curx = x;
  320. cury = y;
  321. }else if(dy == 1)
  322. {
  323. //check for optimal
  324. if(cursx && (*py > cury || (*py == cury && *psx > cursx)))
  325. {
  326. *px = curx - cursx + 1;
  327. *py = cury;
  328. *psx = cursx;
  329. *plsy = curlsy;
  330. *prsy = currsy;
  331. }
  332. cursx = 0;
  333. curlsy = 0;
  334. currsy = 0;
  335. curx = x-1;
  336. cury = y;
  337. }
  338. cursx++;
  339. dx = -1;
  340. dy = 0;
  341. }else
  342. //step up
  343. if(y<ymax)
  344. {
  345. if(dy == -1)
  346. {
  347. curx = x;
  348. cury = y;
  349. }
  350. // if(dy == 1)
  351. curlsy++;
  352. dx = 0;
  353. dy = 1;
  354. }else
  355. {
  356. //something wrong
  357. break;
  358. }
  359. x+=dx;
  360. y+=dy;
  361.  
  362. }
  363. //check for optimal
  364. if(*py > cury || (*py == cury && *psx > cursx))
  365. {
  366. *px = curx - cursx + 1;
  367. *py = cury;
  368. *psx = cursx;
  369. *plsy = curlsy;
  370. *prsy = currsy;
  371. }
  372. if(*psx)
  373. {
  374. if(*plsy == 0)
  375. {
  376. *plsy = ymax - *py;
  377. }
  378. if(*prsy == 0)
  379. {
  380. *prsy = ymax - *py;
  381. }
  382. if(*plsy>*prsy)
  383. {
  384. cury = *plsy;
  385. *plsy = *prsy;
  386. *prsy = cury;
  387. }
  388. return 1;
  389. }
  390. else
  391. return 0;
  392. }
  393. void FillSquare(unsigned short x, unsigned short y, unsigned short sx, unsigned short sy, int stub)
  394. {
  395. int i, j;
  396. unsigned int val;
  397. if(stub)
  398. {
  399. val = -1;
  400. }else
  401. {
  402. val = sx;
  403. val=(val<<16)+sy;
  404. }
  405. for(i = x;i < x+sx;i++)
  406. {
  407. for(j=y;j<y+sy;j++)
  408. {
  409. Square[i][j] = val;
  410. }
  411.  
  412. }
  413. }
  414.  
  415. int __inline SmartFindSum(unsigned short NeedSum, unsigned short HeightPos)
  416. {
  417. int i, MaxItems = 0;
  418. for(i=0;i<Rectangles[HeightPos][0].count;i++)
  419. {
  420. MaxItems += Rectangles[HeightPos][i].count;
  421. }
  422. if(!MaxItems)
  423. return 0;
  424. if(FindSum(MaxItems, NeedSum, HeightPos, Rectangles[HeightPos][0].count,0) == 1)
  425. {
  426. return 1;
  427. }
  428. return 0;
  429. }
  430. void __inline ZeroBestSum()
  431. {
  432. BestSum[0] = 1000;
  433. BestSum[1] = 0;
  434. BestSum[2] = 0;
  435. }
  436. void Prepare(int max)
  437. {
  438. int i ,j;
  439. for(i = 0;i<=max;i++)
  440. {
  441. for(j=0;j<=max;j++)
  442. {
  443. Square[i][j]=0;
  444. }
  445.  
  446. }
  447. for(i = nCountRect;i>=0;i--)
  448. {
  449. Rectangles[i][0].count=0;
  450. Rectangles[i][0].width=0;
  451. }
  452.  
  453. nUsedElements = 0;
  454. ZeroBestSum();
  455.  
  456. }
  457. int FindRectangle(unsigned short Height, unsigned short Width)
  458. {
  459. unsigned short pos;
  460. pos = FindArray(Height, Rectangles[0][0].count);
  461. if(!pos)
  462. return 0;
  463. return SmartFindSum(Width, pos);
  464. }
  465. int LetsPlay(unsigned short xmax, unsigned short ymax)
  466. {
  467.  
  468. unsigned short curx, cury, cursx, curlsy, currsy, pos;
  469. int sumfinded = 0, i, k;
  470. unsigned short TempBestSum[MAXWIDTH +3];
  471. while(FindNextPlace(xmax, ymax, &curx, &cury, &cursx, &curlsy, &currsy))
  472. {
  473. sumfinded = 0;
  474. ZeroBestSum();
  475. sumfinded = FindRectangle(curlsy, cursx);
  476. if(!sumfinded)
  477. {
  478. sumfinded = FindRectangle(currsy, cursx);
  479. }
  480. /*
  481. if(!sumfinded)
  482. {
  483. k = FindArray(curlsy, Rectangles[0][0].count);
  484. if(k && Rectangles[k][0].count && Rectangles[k][1].width <= cursx)
  485. {
  486. BestSum[0] = cursx - Rectangles[k][1].width;
  487. BestSum[1] = 1;
  488. BestSum[2] = curlsy;
  489. BestSum[3] = Rectangles[k][1].width;
  490. sumfinded = 1;
  491. }
  492.  
  493. k = FindArray(currsy, Rectangles[0][0].count);
  494. if(k && Rectangles[k][0].count && Rectangles[k][1].width <= cursx)
  495. {
  496. if(!sumfinded || BestSum[3] > Rectangles[k][1].width)
  497. {
  498. BestSum[0] = cursx - Rectangles[k][1].width;
  499. BestSum[1] = 1;
  500. BestSum[2] = currsy;
  501. BestSum[3] = Rectangles[k][1].width;
  502. sumfinded = 1;
  503. }
  504. }
  505. }
  506.  
  507. */
  508. for(k = 3;!sumfinded && k>1;k--)
  509. {
  510. ZeroBestSum();
  511. FindRectangle(curlsy, cursx/k);
  512. if(BestSum[1] > 0)
  513. {
  514. sumfinded = 1;
  515. }
  516. if(!sumfinded)
  517. {
  518. FindRectangle(currsy, cursx/k);
  519. if(BestSum[1] > 0)
  520. sumfinded = 1;
  521. }
  522. if(sumfinded)
  523. {
  524. BestSum[0] += cursx-cursx/k;
  525. }
  526. }
  527.  
  528. memcpy(TempBestSum, BestSum, (BestSum[1]+3)*sizeof(unsigned short));
  529.  
  530. if(!sumfinded)
  531. {
  532. ZeroBestSum();
  533. if(Rectangles[0][0].count < 1)
  534. return 1;
  535. for(pos = Rectangles[0][0].count;pos>0;pos--)
  536. {
  537. if(Rectangles[pos][0].width > ymax-cury)
  538. continue;
  539. sumfinded = SmartFindSum(cursx, pos);
  540. if(sumfinded)
  541. break;
  542. }
  543. if(TempBestSum[1] && !sumfinded)
  544. memcpy(BestSum, TempBestSum, (TempBestSum[1]+3)*sizeof(unsigned short));
  545. }
  546. if(BestSum[1] > 0)
  547. sumfinded = 1;
  548.  
  549. if(!sumfinded)
  550. {
  551. FillSquare(curx, cury, cursx, curlsy, 1);
  552. }else
  553. {
  554. for(i =0; i<BestSum[1];i++)
  555. {
  556. cursx = BestSum[i+3];
  557.  
  558. if(BestSum[0] != 0 && BestSum[2] > curlsy)
  559. {
  560. FillSquare((unsigned short)(curx + BestSum[0]), cury, cursx, BestSum[2], 0);
  561. }
  562. else
  563. {
  564. FillSquare(curx, cury, cursx, BestSum[2], 0);
  565. }
  566. nUsedElements++;
  567.  
  568. DeleteItem(cursx, BestSum[2]);
  569. curx += cursx;
  570. }
  571. }
  572. }
  573. return 1;
  574. }
  575.  
  576. int PrintSquare(int xmax, int ymax)
  577. {
  578. unsigned short i,j;
  579. printf("%u\n", nUsedElements);
  580. for(i = 0;i<xmax;i++)
  581. {
  582. for(j = 0;j<ymax;j++)
  583. {
  584. if(Square[i][j]!=(unsigned int)-1 && Square[i][j]!=0)
  585. {
  586. printf("%u %u %u %u\n", i+1, j+1, i + (Square[i][j]>>16), j + (Square[i][j]&0xffff));
  587. FillSquare(i, j, (unsigned short)(Square[i][j]>>16), (unsigned short)(Square[i][j]&0xffff),1);
  588. }
  589. }
  590. }
  591. return 1;
  592. }
  593. void GenRandom(int maxc, int maxw)
  594. {
  595. int i, w, h, c;
  596. for(i=0;i<maxc;i++)
  597. {
  598. w = 1+(rand()*(maxw-1))/RAND_MAX;
  599. h = 1+(rand()*(maxw-1))/RAND_MAX;
  600. c = 2;
  601. AddRectangle(w, h, c);
  602. printf("%d %d %d\n", w, h, c);
  603. }
  604. }
  605. void ReadData(int * pmax)
  606. {
  607. int i, n, x,y,c, max;
  608.  
  609. scanf("%d %d", &max, &n);
  610. Prepare(max);
  611. for(i =0;i<n;i++)
  612. {
  613. scanf("%d %d %d", &x, &y, &c);
  614. if(x<=0 || y<=0 || x > max || y > max)
  615. continue;
  616. AddRectangle(x, y, c);
  617. }
  618. // GenRandom((rand()*1000)/RAND_MAX, 10);
  619. SortRectangles();
  620.  
  621. nCountRect = Rectangles[0][0].count;
  622.  
  623. *pmax = max;
  624. }
  625.  
  626.  
  627.  
  628. int main()
  629. {
  630. int i, n, max;
  631.  
  632. srand(time(NULL));
  633. scanf("%d", &n);
  634. for(i = 0;i<n;i++)
  635. {
  636. ReadData(&max);
  637. // if(max > 800)
  638. // {
  639. // printf("0\n");
  640. // continue;
  641. // }
  642. if(!LetsPlay(max, max))
  643. return 1;
  644. if(!PrintSquare(max, max))
  645. return 1;
  646. }
  647.  
  648. return 0;
  649. }