題解:子矩陣(NOIP2014普及組T4)
阿新 • • 發佈:2018-10-31
+= out bsp tdi 又是 style 預處理 sizeof 表示
又是dp
暴力枚舉會T
考慮先固定一個變量,比如先枚舉行
然後預處理每行之間的絕對值,每列之間的絕對值
然後dp進行轉移
註意記錄選擇的行數
轉移記得加上新選的列的行之間的絕對值,即w[i],
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 int n, m, r, c; 7 int a[20][20], f[20][20];//f[i][j]表示選擇了i列,最後一列為j8 int w[20], v[20][20], path[20]; 9 int ans=1<<30; 10 void work(){ 11 memset(f,127,sizeof(f)); 12 memset(w,0,sizeof(w)); 13 memset(v,0,sizeof(v)); 14 for(int i=1; i<=m; i++) 15 for(int j=1; j<r; j++) 16 w[i]+=abs(a[path[j]][i]-a[path[j+1]][i]); //記錄已選擇的行之間第i列的絕對值 17 for(int i=1; i<=m; i++) 18 for(int j=i+1; j<=m; j++) 19 for(int k=1; k<=r; k++) 20 v[i][j]+=abs(a[path[k]][i]-a[path[k]][j]); //預處理每列之間的絕對值差 21 f[0][0]=0; 22 for(int i=1; i<=c; i++) 23 for(int j=i; j<=m; j++)24 for(int k=0; k<j; k++) 25 f[i][j]=min(f[i][j], f[i-1][k]+w[j]+v[k][j]);//dp 26 for(int i=c; i<=m; i++) ans=min(ans, f[c][i]); //尋找答案 27 28 } 29 void dfs(int now, int pre){ 30 if(now>r){ 31 work(); 32 return ; 33 } 34 for(int i=pre+1; n-i>=r-now; i++){ 35 path[now]=i; 36 dfs(now+1, i); 37 } 38 } 39 int main(){ 40 scanf("%d%d%d%d",&n,&m,&r,&c); 41 for(int i=1; i<=n; ++i) 42 for(int j=1; j<=m; ++j) 43 scanf("%d",&a[i][j]); 44 dfs(1, 0); 45 cout<<ans<<endl; 46 return 0; 47 }
題解:子矩陣(NOIP2014普及組T4)