P2258 子矩阵
題目描述
給出如下定義:
例如,下面左圖中選取第 222 、 444 行和第 222 、 444 、 555 列交叉位置的元素得到一個 2×32 \times 32×3 的子矩陣如右圖所示。
9 3 3 3 9
9 4 8 7 4
1 7 4 6 6
6 8 5 6 9
7 4 5 6 1
的其中一個 2×32 \times 32×3 的子矩陣是
4 7 4
8 6 9
相鄰的元素:矩陣中的某個元素與其上下左右四個元素(如果存在的話)是相鄰的。
矩陣的分值:矩陣中每一對相鄰元素之差的絕對值之和。
本題任務:給定一個 nnn 行 mmm 列的正整數矩陣,請你從這個矩陣中選出一個 rrr 行 ccc 列的子矩陣,使得這個子矩陣的分值最小,并輸出這個分值。
(本題目為2014NOIP普及## 題目描述
給出如下定義:
例如,下面左圖中選取第 222 、 444 行和第 222 、 444 、 555 列交叉位置的元素得到一個 2×32 \times 32×3 的子矩陣如右圖所示。
9 3 3 3 9
9 4 8 7 4
1 7 4 6 6
6 8 5 6 9
7 4 5 6 1
的其中一個 2×32 \times 32×3 的子矩陣是
4 7 4
8 6 9
相鄰的元素:矩陣中的某個元素與其上下左右四個元素(如果存在的話)是相鄰的。
矩陣的分值:矩陣中每一對相鄰元素之差的絕對值之和。
本題任務:給定一個 nnn 行 mmm 列的正整數矩陣,請你從這個矩陣中選出一個 rrr 行 ccc 列的子矩陣,使得這個子矩陣的分值最小,并輸出這個分值。
(本題目為2014NOIP普及T4)
輸入輸出格式
輸入格式:
第一行包含用空格隔開的四個整數 n,m,r,cn,m,r,cn,m,r,c ,意義如問題描述中所述,每兩個整數之間用一個空格隔開。
接下來的 nnn 行,每行包含 mmm 個用空格隔開的整數,用來表示問題描述中那個 nnn 行 mmm 列的矩陣。
輸出格式:
一個整數,表示滿足題目描述的子矩陣的最小分值。
輸入輸出樣例
輸入樣例#1: 復制
5 5 2 3
9 3 3 3 9
9 4 8 7 4
1 7 4 6 6
6 8 5 6 9
7 4 5 6 1
輸出樣例#1: 復制
6
輸入樣例#2: 復制
7 7 3 3
7 7 7 6 2 10 5
5 8 8 2 1 6 2
2 9 5 5 6 1 7
7 9 3 6 1 7 8
1 9 1 4 7 8 8
10 5 9 1 1 8 10
1 3 1 5 4 8 6
輸出樣例#2: 復制
16
說明
【輸入輸出樣例1說明】
該矩陣中分值最小的 222 行 333 列的子矩陣由原矩陣的第 444 行、第 555 行與第 111 列、第 333 列、第 444 列交叉位置的元素組成,為
6 5 6
7 5 6
,其分值為:
|6?5| + |5?6| + |7?5| + |5?6| + |6?7| + |5?5| + |6?6| =6。
【輸入輸出樣例2說明】
該矩陣中分值最小的3行3列的子矩陣由原矩陣的第 444 行、第 555 行、第 666 行與第 222 列、第 666 列、第 777 列交叉位置的元素組成,選取的分值最小的子矩陣為
9 7 8
9 8 8
5 8 10
【數據說明】
對于 50%50%50% 的數據, 1≤n≤12,1≤m≤121 ≤ n ≤ 12,1 ≤ m ≤ 121≤n≤12,1≤m≤12 ,矩陣中的每個元素 1≤aij≤201 ≤ a_{ij} ≤ 201≤aij?≤20 ;
對于 100%100%100% 的數據, 1≤n≤16,1≤m≤161 ≤ n ≤ 16,1 ≤ m ≤ 161≤n≤16,1≤m≤16 ,矩陣中的每個元素 1≤aij≤1,000,1≤r≤n,1≤c≤m1 ≤ a_{ij} ≤ 1,000,1 ≤ r ≤ n,1 ≤ c ≤ m1≤aij?≤1,000,1≤r≤n,1≤c≤m 。T4)
輸入輸出格式
輸入格式:
第一行包含用空格隔開的四個整數 n,m,r,cn,m,r,cn,m,r,c ,意義如問題描述中所述,每兩個整數之間用一個空格隔開。
接下來的 nnn 行,每行包含 mmm 個用空格隔開的整數,用來表示問題描述中那個 nnn 行 mmm 列的矩陣。
輸出格式:
一個整數,表示滿足題目描述的子矩陣的最小分值。
輸入輸出樣例
輸入樣例#1: 復制
5 5 2 3
9 3 3 3 9
9 4 8 7 4
1 7 4 6 6
6 8 5 6 9
7 4 5 6 1
輸出樣例#1: 復制
6
輸入樣例#2: 復制
7 7 3 3
7 7 7 6 2 10 5
5 8 8 2 1 6 2
2 9 5 5 6 1 7
7 9 3 6 1 7 8
1 9 1 4 7 8 8
10 5 9 1 1 8 10
1 3 1 5 4 8 6
輸出樣例#2: 復制
16
說明
【輸入輸出樣例1說明】
該矩陣中分值最小的 222 行 333 列的子矩陣由原矩陣的第 444 行、第 555 行與第 111 列、第 333 列、第 444 列交叉位置的元素組成,為
6 5 6
7 5 6
,其分值為:
|6?5| + |5?6| + |7?5| + |5?6| + |6?7| + |5?5| + |6?6| =6。
【輸入輸出樣例2說明】
該矩陣中分值最小的3行3列的子矩陣由原矩陣的第 444 行、第 555 行、第 666 行與第 222 列、第 666 列、第 777 列交叉位置的元素組成,選取的分值最小的子矩陣為
9 7 8
9 8 8
5 8 10
【數據說明】
對于 \(50\%\)的數據, \(1 ≤ n ≤ 12,1 ≤ m ≤ 12\),矩陣中的每個元素 \(1 ≤ a_{ij} ≤ 20\);
對于 \(100\%\) 的數據, \(1≤n≤16,1≤m≤16\) ,矩陣中的每個元素 \(1 ≤ a_{ij} ≤ 1,000,1 ≤ r ≤ n,1 ≤ c ≤ m\)。
先爆搜出\(r\)行,再在選出的行中dp選出\(c\)列即可
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std;int i,m,n,j,k,a[20][20],b[20][20],r,c,d[20],w[20],f[20][20],ans=0x3f3f3f3f;void dp() {memset(w,0,sizeof(w));memset(b,0,sizeof(b));memset(f,0x3f,sizeof(f));for(int i=1;i<=m;i++)for(int j=2;j<=r;j++) w[i]+=abs(a[d[j]][i]-a[d[j-1]][i]);for(int i=1;i<m;i++)for(int j=i+1;j<=m;j++) for(int l=1;l<=r;l++)b[i][j]+=abs(a[d[l]][i]-a[d[l]][j]);f[0][0]=0;for(int i=1;i<=m;i++)for(int j=1;j<=min(i,c);j++)for(int l=j-1;l<i;l++)f[i][j]=min(f[i][j],f[l][j-1]+b[l][i]+w[i]);for(int i=c;i<=m;i++) ans=min(ans,f[i][c]); }void dfs(int k,int now) {if(k==r) {dp(); return;}for(int i=now;i<=n-r+k+1;i++) d[k+1]=i,dfs(k+1,i+1); }int main() {scanf("%d%d%d%d",&n,&m,&r,&c);for(i=1;i<=n;i++)for(j=1;j<=m;j++) scanf("%d",&a[i][j]);dfs(0,1);printf("%d",ans); }轉載于:https://www.cnblogs.com/ZUTTER/p/9509605.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: 关于编程思想的一点思考
- 下一篇: SELinux 引起的 Docker 启