[NOIP2014]子矩阵解题报告
来源:互联网 发布:java线程同步几种方式 编辑:程序博客网 时间:2024/05/29 08:18
这题看上去没啥思路,一看数据范围小的可怜,就算了下暴搜的时间复杂度
结果一看人家的代码全是DP。。让我有点蛋疼。
其实只要把暴搜的后半部分一改就可以了,把二维压成一维后,就有一个显然的DP方程:处理出选一列的代价
= =这里实际上还有一个问题,就是暴搜出所有组合的时间复杂度是多少。我们在n个数中选择m个,我们采用从前往后暴搜01串的搜索方式,并加上这样两个剪枝:如果当前搜出的1的个数大于m,剪枝;如果即使剩下的数的个数全选1也不足以凑齐m个,则剪枝。那么我们试图分析一下这两个剪枝的效果,第一个剪枝好说,第二个剪枝的话,我们考虑在还剩m-x个时它减掉的叶节点数目(要求它不能被还剩m-(x-1)时减掉),那么可以得到这样一个显然的式子:
这应该说是一个相当惊人的结论了,我们尝试证明这个结论,即证明等式
——②注意到这两个
但是2的幂和组合数乘起来了,我并不会处理这种东西,这让我很蛋疼;不过如果我们把它们放到杨辉三角中,发现右边是在左边上面的一条有系数的斜线,于是我们以第n行系数全为1开始向上推,这时我们惊奇的发现第n-1行的系数是2…21(m-1个2),而边界正是左边的第一项,而第n-2行的系数是4…42(m-2个4),于是我们似乎便可以以这样不严谨的方式证明了上述神奇的时间复杂度了!
Code(dfs):
#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int n,m,r,c;int a[20][20];int ls[20],hs[20][20];int list[20];int ans=0x7fffffff;inline void ldfs(int x,int last,int nowc,int nowsum){ if(m-x<nowc||nowsum>=ans)return; if(x==m){ ans=min(ans,nowsum); return; } ldfs(x+1,last,nowc,nowsum); if(nowc)ldfs(x+1,x,nowc-1,nowsum+ls[x]+hs[last][x]);}inline void hdfs(int x,int now){ if(n-x<now)return; if(x==n){ int i,j; memset(ls,0,sizeof(ls)); for(i=m;i--;) for(j=r;--j;) ls[i]+=abs(a[list[j]][i]-a[list[j-1]][i]); int k; memset(hs,0,sizeof(hs)); for(i=0;i<m;++i) for(j=i+1;j<m;++j) for(k=r;k--;) hs[i][j]+=abs(a[list[k]][i]-a[list[k]][j]); ldfs(0,m-1,c,0); return; } hdfs(x+1,now); if(now){ list[--now]=x; hdfs(x+1,now); }}int main(){ freopen("submatrix.in","r",stdin); freopen("submatrix.out","w",stdout); scanf("%d%d%d%d",&n,&m,&r,&c); int i,j; for(i=0;i<n;++i) for(j=0;j<m;++j) scanf("%d",a[i]+j); hdfs(0,r); printf("%d\n",ans);}
Code(DP):
#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int n,m,r,c;int a[20][20];int ls[20],hs[20][20];int list[20];int ans=0x7fffffff;int f[20][20];inline void ldfs(int x,int last,int nowc,int nowsum){ int i,j; for(i=0;i<m;++i) for(j=0;j<=c;++j) f[i][j]=1E9; for(i=0;i<m;++i)f[0][0]=0,f[i][1]=ls[i]; int k; for(i=1;i<m;++i) for(j=2;j<=c;++j){ for(k=0;k<i;++k)f[i][j]=min(f[i][j],f[k][j-1]+hs[k][i]); f[i][j]+=ls[i]; } for(i=0;i<m;++i)ans=min(ans,f[i][c]);}inline void hdfs(int x,int now){ if(n-x<now)return; if(x==n){ int i,j; memset(ls,0,sizeof(ls)); for(i=m;i--;) for(j=r;--j;) ls[i]+=abs(a[list[j]][i]-a[list[j-1]][i]); int k; memset(hs,0,sizeof(hs)); for(i=0;i<m;++i) for(j=i+1;j<m;++j) for(k=r;k--;) hs[i][j]+=abs(a[list[k]][i]-a[list[k]][j]); ldfs(0,m-1,c,0); return; } hdfs(x+1,now); if(now){ list[--now]=x; hdfs(x+1,now); }}int main(){ freopen("submatrix.in","r",stdin); freopen("submatrix.out","w",stdout); scanf("%d%d%d%d",&n,&m,&r,&c); int i,j; for(i=0;i<n;++i) for(j=0;j<m;++j) scanf("%d",a[i]+j); hdfs(0,r); printf("%d\n",ans);}
3 0
- [NOIP2014]子矩阵解题报告
- NOIP2014普及组复赛子矩阵解题报告
- NOIP2014 子矩阵
- 【noip2014普及】子矩阵
- HDU 1559 最大子矩阵 解题报告
- NOIP2014解方程解题报告
- 【NOIP2014】洛谷2258 子矩阵
- NOIP2014提高组复赛解题报告
- NOIP2014 联合权值 解题报告
- NOIP2014普及组解题报告 -----by IAMACER
- 【NOIP2014提高组】【Day1】【解题报告】
- 【noip2014提高组】【Day2】【解题报告】
- NOIP2014 提高组复赛解题报告
- codevs 3732 NOIP2014 解方程 解题报告
- [CODEVS1159]最大全0子矩阵解题报告
- 洛谷 1578 奶牛沐场 最大子矩阵 解题报告
- [NOIP2014][vijos1914]子矩阵(dp)
- [noip2014]子矩阵(dfs+dp)
- 30天自制操作系统day2
- centos7上owncloud搭建私有云
- 多种方式计算多项式a0+a1*x+a2*x^2+a3*x^3+.......(计算效率与算法的重要性)
- 漫谈经典排序算法:四、归并排序(合并排序)
- MySQL性能优化的最佳20+条经验
- [NOIP2014]子矩阵解题报告
- Sql查询与删除数据库重复数据
- python编写科学计算程序的书籍
- eclipse常用快捷键
- 数字通信系统模型
- 360笔试 给定a,b字符串 求出b相对于a的相对路径
- 《高效能程序员的修炼》之培养写作习惯
- interceptor拦截器实现aop
- Mac OS安装MySQL(使用二进制PGK包安装)