題意:給定一8*8的棋盤,每次沿著邊將棋盤切成兩部份,把一部分放到一邊,再繼續切另一部分,切n-1次得到n個矩形塊,問使n個塊的和能達到的最小方差。
題解:顯然可以每次遍歷對矩形塊的橫切和豎切,當dfs到份數等於1,利用二維線段樹組將矩形塊的和求出來返回即可。
剪枝:當訪問到同個矩形塊,相同切割份數時,利用儲存的值直接返回即可。
乙個n*m的矩形塊,易知如果n,m不等,最多份數的切割必定是先把矩形一步步切成正方形,然後對正方形邊緣一步步切割得到1*1的矩形塊,假設n,m為8*7,則最大份數的切割方案為:8*7->7*7->7*6->6*6->...->2*1->1*1,歸納的n*m的矩形塊最多可劃分n+m-1份。
#include#include#include#includeusing namespace std;
#define square(x) ((x)*(x))
class solve
int processin();
int low_bit(int x);
int addsum(int x,int y,int val);
int sumbranch(int x,int y);
int calcsum(int left_x,int left_y,int right_x,int right_y);
int dfs(int left_x,int left_y,int right_x,int right_y,int n);
};int solve::dfs(int left_x,int left_y,int right_x,int right_y,int n)
int i;
int val1,val2;
for(i = left_x+1;i < right_x;i++) //遍歷可能的所有的縱切
val1 = dfs(left_x,left_y,i,right_y,1);
val2 = dfs(i,left_y,right_x,right_y,n-1);
if(val1 != -1&&val2 != -1)
}for(i = left_y+1;i < right_y;i++) //遍歷可能的所有橫切
val1 = dfs(left_x,left_y,right_x,i,1);
val2 = dfs(left_x,i,right_x,right_y,n-1);
if(val1 != -1&&val2 != -1)
}minsquare[left_x][left_y][right_x][right_y][n] = tmpval;
return tmpval == 1e8?-1:tmpval;
}int solve::sumbranch(int x,int y)
}return tmpsum;
}int solve::calcsum(int left_x,int left_y,int right_x,int right_y)
int solve::low_bit(int x)
int solve::addsum(int x,int y,int val)
}return 0;
}int solve::processin()
}meanval /= n;
return 0;
}int main()
return 0;
}
poj 1191 棋盤分割
棋盤分割 time limit 1000ms memory limit 10000k total submissions 10807 accepted 3798 description 將乙個 的棋盤進行如下分割 將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩下的部分繼續如此分割,這樣割了 n...
POJ 1191 棋盤分割
題目點我 經典的動態規劃題目,首先將標準差公式變形一下 ni 1 xi x 2n n 2 x 2 i 1nx 2i由於x 是固定的,與分割方案無關,所以求最小的標準差就相當於求最小的平方和的分割方案。定義狀態需要五個維度 描述乙個矩形需要四個維度 左上角座標x1 y1 和右下角座標x2 y2 要分割...
棋盤分割 POJ 1191
1 題目型別 dp 概率論。2 解題思路 dp遞推式 以上下切為例 for i x1.x2 sum k x1 y1 x2 y2 min 其中 i 表示切割位置,k 表示切割次數。3 注意事項 遞迴迴圈的呼叫。4 參考部落格 5 實現方法 include iostream include cmath ...