SGU 167.I-country

來源:互聯網
上載者:User

標籤:style   blog   http   使用   os   io   for   ar   

時間限制:0.75s

空間限制:6M

題意:

       在一個n*m(n,m<=15)的網格中,每個格子有一個值,現在從網格中取出k(k<=n*m)個,保證在選中的格子中從任意一個格子去另外的所有格子最多隻用到四種(上,下,左,右)操作中的兩種,並使得到的值最大。輸出該值和選中的格子座標。

       

 

 

 

Solution

    從選中的網格的任意一個去所有格子只用兩種操作:

          

             左圖一種滿足條件的網格集合,右圖的(1,3)到(3,2)必需使用(左,下,右)三種操作才能到達,是不符合要求的。

 

             注意到,滿足條件的網格集合一定不會出現凹形,因為凹形的上下兩個突出點中的格子不可能只用兩個操作到達。

 

             由此用0,1記錄左右兩邊是 向外突出還是向內收縮。

             當一行的一邊向內收縮時便不可以再向外突出了。

             

             接下來是按行dp

             f[row][l][r][opl][opr][k],代表第row行,取第l列帶第r列的格子,左邊格子突出狀態為opl,右邊為opr,當前共選擇了k個格子

 

             記錄路徑時如果用結構體記錄下所有的狀態的上一個狀態需要15*15*2*2*225 * size(int)*6的空間.

             爆一次記憶體後,想到對於上一個狀態row和k可以推出,只需要記錄(l,r,opl,opr)即可,而(l,r,opl,opr)都是不超過16的數,那麼可以用一個int形用16進位存下

             存的時候用 record=(l << 12) + (r << 8) + (opl << 4) + (opr)

             用的時候

             上一個(row,l,r,opl,opr,k)

             可以由當前的(row - 1, (record >> 12) % 16, (record >> 8) % 16, (record >> 4) % 16, record % 16, k - r + l - 1)得到

  

             這道題需要注意的地方有很多,不一一列舉.總的來說是一道值得一做的好題

參考代碼:

#include <iostream>#include <cstring>#include <cstdio>#define pdx pr[row][l][r][opl][opr][k]#define val(r,a,b) g[r][b] - g[r][a - 1]using namespace std;int f[16][16][16][2][2][230], g[16][16];int pr[16][16][16][2][2][230];int n, m, k, ans;int a, al, ar, aol, aor;/*       op=0    /  左突       op=1    \  右突*///目前狀態向下更新void update (int row, int l, int r, int opl, int opr, int s) {if (row == n) return ;for (int nl = (opl == 0 ? 1 : l); nl <= r; nl++)for (int nr = max (l, nl); nr <= (opr == 0 ? r : m); nr++) {int t1, t2;if (nl == l) t1 = opl;elset1 = (nl < l ? 0 : 1);if (nr == r) t2 = opr;elset2 = (nr < r ? 0 : 1);if (f[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] <                              f[row][l][r][opl][opr][s] + val (row + 1, nl, nr) ) {f[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] =                              f[row][l][r][opl][opr][s] + val (row + 1, nl, nr);//記錄上一個狀態   ,  16進位狀態壓縮pr[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] =              (l << 12) + (r << 8) + (opl << 4) + (opr);}}}void dp() {for (int row = 1; row <= n; row++)for (int l = 1; l <= m; l++)for (int r = l; r <= m; r++)for (int opl = 0; opl < 2; opl++)for (int opr = 0; opr < 2; opr++) {f[row][l][r][opl][opr][r - l + 1] = g[row][r] - g[row][l - 1];for (int s = r - l + 1; s <= k; s++)if (f[row][l][r][opl][opr][s] > 0 ) {update (row, l, r, opl, opr, s);if (s == k)//記錄最大解if (f[row][l][r][opl][opr][s] > ans) {ans = f[row][l][r][opl][opr][s];a = row, al = l, ar = r, aol = opl, aor = opr;}}}}//輸出void write (int row, int l, int r, int opl, int opr, int k) {if (row == 0 || k <= 0) return;for (int i = l; i <= r; i++)printf ("%d %d\n", row, i);write (row - 1, (pdx >> 12) % 16, (pdx >> 8) % 16,                      (pdx >> 4) % 16, pdx % 16, k - r + l - 1);}int main() {#ifndef ONLINE_JUDGEfreopen ("in.txt", "r", stdin);#endif // oline_judgescanf ("%d %d %d", &n, &m, &k);for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++) {scanf ("%d", &g[i][j]);g[i][j] += g[i][j - 1];}memset (f, -1, sizeof f);dp();printf ("Oil : %d\n", ans);write (a, al, ar, aol, aor, k);return 0;}

  

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.