トピック:https://www.luogu.org/problem/P1436 タイトル説明次のように8×8のチェッカーボードが分類される:元の長方形の市松模様の部分を切断し、残りの部分は長方形の基板であり、その後分割の残りの2つの部分は、そうし続けるようにカット(N-1)時間後に、n個のブロック矩形ボードの最後に残った長方形の市松模様の合計と一緒。(各カットは、チェス盤の側面に沿って行うことができます)
基板上の各セルは、その合計スコアに含まれる各グリッド矩形ボードのスコアを元のスコアを有します。今、我々は、長方形の基板のn個のブロックに上記の規則によってチェスボードする必要があり、最小二乗和のうち、各長方形のボード。 正方形の最小合計を取得し、ボード・プログラミングとnをお願いします。 入力形式最初の整数n(1 <N <15)を行います。 2、非負整数100を行うために8時間毎行目にライン9は、基板の対応するセルの値を表します。各隣接する行は、二つの数字の間のスペースで区切られました。 出力フォーマット二乗和のための数だけ、。 |
典型的なDPのタイトルは、アイデアは、私たちは各長方形のため、私たちは考えるの左上隅(a、b)は、右下隅(C、D)矩形を記述するために(A、B、C、D)を使用し、非常に簡単です垂直に切断することが次の目標として、その二つのうちの一つを検討するためにあらゆる時間を削減し、バックカットバックや横に切ります。
最適化:説明和[I]、[J](1,1、i、j)の領域、および除外を求めた矩形領域。
コードの場合:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 const int inf=1e9; 6 int n; 7 int ma[20][20]; 8 int sum[20][20]; 9 int dp[20][20][20][20][20]; 10 int cal(int a,int b,int c,int d){ 11 return sum[c][d]+sum[a-1][b-1]-sum[c][b-1]-sum[a-1][d]; 12 } 13 int main(){ 14 scanf("%d",&n); 15 for(int i=1;i<=8;i++){ 16 for(int j=1;j<=8;j++){ 17 scanf("%d",&ma[i][j]); 18 sum[i][j]=sum[i-1][j]+sum[i][j-1]+ma[i][j]-sum[i-1][j-1]; 19 } 20 } 21 for(int a=1;a<=8;a++){ 22 for(int b=1;b<=8;b++){ 23 for(int c=a;c<=8;c++){ 24 for(int d=b;d<=8;d++){ 25 dp[a][b][c][d][0]+=cal(a,b,c,d); 26 dp[a][b][c][d][0]*=dp[a][b][c][d][0]; 27 } 28 } 29 } 30 } 31 for(int t=1;t<n;t++) 32 for(int a=1;a<=8;a++){ 33 for(int b=1;b<=8;b++){ 34 for(int c=a;c<=8;c++){ 35 for(int d=b;d<=8;d++){ 36 int q=inf; 37 for(int y=b;y<d;y++){ 38 q=min(q,min(dp[a][b][c][y][0]+dp[a][y+1][c][d][t-1],dp[a][y+1][c][d][0]+dp[a][b][c][y][t-1])); 39 } 40 for(int x=a;x<c;x++){ 41 q=min(q,min(dp[x+1][b][c][d][0]+dp[a][b][x][d][t-1],dp[x+1][b][c][d][t-1]+dp[a][b][x][d][0]));//这两句容易错,注意考虑切入点与区间关系 42 } 43 dp[a][b][c][d][t]=q; 44 } 45 } 46 } 47 } 48 // for(int i=1;i<=8;i++){ 49 // for(int j=1;j<=8;j++){ 50 // cout<<sum[i][j]<<" "; 51 // } 52 // cout<<endl; 53 // } 54 cout<<dp[1][1][8][8][n-1]<<endl; 55 return 0; 56 }