标签:P2258 int 矩阵 cin dfs line include 233
子矩阵
思路
很容易想到这是一个动态规划,但是从题目来分析,不能很容易的设计出状态转移方程。
原题为从矩阵中选出r行c列
我们可以将问题进行化简,先对于原题进行dfs枚举行数
对于每次枚举出来的r行m列,再进行一次动态规划
对于在r行m列中选出c列来,其转移方程就非常容易得到了
\[f[i][j] = min_(f[k][j-1]+w[i]+v[k][i]) \]
其中\(w\)数组是每列中元素的分值
而\(v[i][j]\)则是第\(i\)与第\(j\)之间的分值
\(f[i][j]\)是选第\(i\)列作为第\(j\)行最小值
\(f\)数组初始化为$$f[i][1]=w[i]$$
总程序的时间复杂度主要由两部分构成
dfs O(\(C_n^r\))
动态规划 O(\(m^3\))
总时间复杂度为O(\(C_n^rm^3\))
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int a[23][233];
int f[233][23];
int v[233][233];
int p[2333];
int w[2333];
int n,m;
int r,c;
int minn=1<<30;
inline void dtgh()
{
memset(f,0x7f,sizeof(f));
memset(w,0,sizeof(w));
memset(v,0,sizeof(v));
for(int i=1;i<=m;i++)
{
for(int j=2;j<=r;j++)
w[i]+=abs(a[p[j-1]][i]-a[p[j]][i]);
}
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
{
if(i == j) continue;
for(int t=1;t<=r;t++)
v[i][j]+=abs(a[p[t]][i]-a[p[t]][j]);
}
for(int i=1;i<=m;i++)
{
f[i][1]=w[i];
}
for(int i=1;i<=m;i++)
for(int j=1;j<=min(c,i);j++)
{
for(int k=j-1;k<i;k++)
f[i][j]=min(f[i][j],f[k][j-1]+w[i]+v[k][i]);
}
for(int i=1;i<=m;i++)
minn=min(minn,f[i][c]);
}
inline void dfs(int line,int step)
{
if(step == r+1)
{
dtgh();
return ;
}
if(line > n) return;
p[step]=line;
dfs(line+1,step+1);
dfs(line+1,step);
}
int main()
{
ios_base::sync_with_stdio(false);
cout.tie(NULL);
cin.tie(NULL);
cin>>n>>m;
cin>>r>>c;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
dfs(1,1);
cout<<minn;
}
end
标签:P2258,int,矩阵,cin,dfs,line,include,233 来源: https://www.cnblogs.com/-Iris-/p/13405581.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。