版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/83116632
题解:
这道题真tm恶心啊。
颜色数小就直接斯坦树了,颜色大的话则考虑给每个颜色随机映射到
的颜色中,这样的正确率就是
,概率大概在0.006。多随机几百次就过了。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=17, M=(1<<7)+20, B=1e5+50, inf=1e9, T=550;
const int fx[]={0,0,-1,1};
const int fy[]={1,-1,0,0};
int n,m,tot,k,bin[N],ans=inf;
#define gi(x,y) ((x-1)*m+y)
int f[N*N][M],c[N*N],v[N*N],w[N*N];
int g[N*N],vt[N*N*8],nt[N*N*8],ec;
int q[B],exi[N*N],r;
inline void add(int x,int y) {nt[++ec]=g[x]; g[x]=ec; vt[ec]=y;}
struct data {
int x,y,w;
data(int x,int y,int w) : x(x),y(y),w(w) {}
};
inline unsigned int unit() {
static unsigned int x=2333;
x^=(x<<5);x^=(x>>17);x^=(x<<13);
return x;
}
inline void solve() {
for(int i=1;i<=tot;i++)
for(int sta=0;sta<bin[k];sta++)
f[i][sta]=inf;
map <int,int> id;
for(int i=1;i<=tot;i++) if(c[i]>0) {
if(!id.count(c[i])) id[c[i]]=unit()%k;
v[i]=id[c[i]];
}
for(int i=1;i<=tot;i++)
if(~c[i]) f[i][0]=w[i];
for(int sta=0;sta<bin[k];sta++) {
for(int i=1;i<=tot;i++) if(~c[i]) {
if(c[i] && (sta&bin[v[i]])) f[i][sta]=min(f[i][sta],f[i][sta^bin[v[i]]]);
for(int s=sta;s>sta^s;s=(s-1)&sta)
f[i][sta]=min(f[i][sta],f[i][s]+f[i][sta^s]-w[i]);
}
r=0;
for(int i=1;i<=tot;i++) if(~c[i])
if(f[i][sta]<ans) q[++r]=i, exi[i]=1;
for(int i=1;i<=r;i++) {
int u=q[i], uw=f[u][sta]; exi[u]=0;
for(int e=g[u];e;e=nt[e]) {
int v=vt[e];
if(~c[v] && f[v][sta]>uw+w[v]) {
f[v][sta]=uw+w[v];
if(!exi[v] && f[v][sta]<ans) exi[v]=1, q[++r]=v;
}
}
}
}
for(int i=1;i<=tot;i++) ans=min(ans,f[i][bin[k]-1]);
}
int main() {
n=rd(), m=rd(), k=rd(); tot=n*m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) c[gi(i,j)]=rd();
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) w[gi(i,j)]=rd();
for(int i=0;i<=k;i++) bin[i]=1<<i;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(~c[gi(i,j)]) for(int z=0;z<4;z++) {
int i2=i+fx[z], j2=j+fy[z];
if(i2<1 || i2>n || j2<1 || j2>m || !~c[gi(i2,j2)]) continue;
add(gi(i,j),gi(i2,j2));
}
for(int i=T;i;i--) solve();
printf("%d\n",(ans==inf) ? -1 : ans);
}