拯救莫莉斯题解
拯救莫莉斯题解
实际上是水题啦,
观察数据发现,\(m*n<=50,m<=n\),所以\(m<=sqrt(50)\)即\(m<=7\)
只可能是状压啊,搜索啊,矩阵啊
但是矩阵一般有一项非常大,大到\(O(n)\)做不了,所以基本排除,
搜索基本不可能的,毕竟吗m*n还是有50的,
所以状压,
水啊,
上代码吧:
#include<bits/stdc++.h>
using namespace std;
const int N=56,M=147;
int n,m,t,p,g[N][M],f[N][M][M],q[N][M][M],o[M],ans1=2e9,ans2=2e9;
inline int read(){
int T=0,F=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
return F*T;
}
int main(){
n=read(),m=read(),p=(1<<m)-1,memset(f,0x3f,sizeof(f));
for(int i=0;i<m;++i) for(int j=1;j<=p;++j) if(j&(1<<i)) ++o[j];
for(int i=1;i<=n;++i)
for(int j=0;j<m;++j){
t=read();
for(int k=p;k>=1;--k) if(k&(1<<j)) g[i][k]+=t;
}
for(int i=0;i<=p;++i) f[1][0][i]=g[1][i],q[1][0][i]=o[i];
for(int i=2;i<=n+1;++i)
for(int k=0;k<=p;++k){
for(int j=0;j<=p;++j){
for(int w=0;w<=p;++w)
if(((j|k|(k<<1)|(k>>1)|w)&p)==p&&(f[i][k][j]>f[i-1][w][k]+g[i][j]||(f[i][k][j]==f[i-1][w][k]+g[i][j]&&q[i][k][j]>q[i-1][w][k]+o[j])))
f[i][k][j]=f[i-1][w][k]+g[i][j],q[i][k][j]=q[i-1][w][k]+o[j];
}
}
for(int i=0;i<=p;++i) if(ans1>f[n+1][i][0]||(ans1==f[n+1][i][0]&&ans2>q[n+1][i][0])) ans1=f[n+1][i][0],ans2=q[n+1][i][0];
printf("%d %d\n",ans2,ans1);
return 0;
}