loj2977 巧克力 (斯坦纳树+随机化)
考虑颜色比较少的时候,第一问可以直接斯坦纳树
第二问考虑二分,每次把每格的权值给成1000+[a[i]>m],就是在个数最少的基础上尽量选小于等于m的
然而颜色太多不能直接做,但可以把每种颜色映射到5以内,这样的话,做一次的正确率就是作为答案的那5种颜色分别被映射到了1~5的概率,就是$\frac{5!}{5^5}=0.0384$,做233次正确率就有$99.989\%$了
1 #include<bits/stdc++.h> 2 #include<tr1/unordered_map> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 #define fi first 6 #define se second 7 using namespace std; 8 typedef long long ll; 9 typedef unsigned long long ull; 10 typedef long double ld; 11 typedef pair<int,int> pa; 12 const int maxn=250,maxp=50; 13 14 inline ll rd(){ 15 ll x=0;char c=getchar();int neg=1; 16 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 17 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 18 return x*neg; 19 } 20 21 int step[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; 22 int id[maxn][maxn],pct,pos[maxn][2]; 23 int N,M,S,K; 24 int f[maxn][maxp],c[maxn],a[maxn],val[maxn]; 25 int hsh[maxn],C; 26 27 queue<int> q; 28 bool flag[maxn]; 29 inline void spfa(int s){ 30 for(int i=1;i<=pct;i++) if(c[i]!=-1) flag[i]=1,q.push(i); 31 32 while(!q.empty()){ 33 int p=q.front();q.pop(); 34 flag[p]=0; 35 int x=pos[p][0],y=pos[p][1]; 36 for(int j=0;j<4;j++){ 37 int nx=x+step[j][0],ny=y+step[j][1]; 38 if(nx<1||ny<1||nx>N||ny>M||c[id[nx][ny]]==-1) continue; 39 int ni=id[nx][ny]; 40 if(f[ni][s]>f[p][s]+val[ni]){ 41 f[ni][s]=f[p][s]+val[ni]; 42 if(!flag[ni]) q.push(ni),flag[ni]=1; 43 } 44 } 45 } 46 } 47 48 inline int solve(){ 49 CLR(f,63); 50 for(int i=1;i<=pct;i++) if(c[i]!=-1) f[i][1<<hsh[c[i]]]=val[i]; 51 for(int s=1;s<(1<<K);s++){ 52 for(int i=1;i<=pct;i++){ 53 if(c[i]==-1) continue; 54 for(int ss=(s-1)&s;ss;ss=(ss-1)&s){ 55 f[i][s]=min(f[i][s],f[i][ss]+f[i][s^ss]-val[i]); 56 } 57 } 58 spfa(s); 59 } 60 int ans=1e9; 61 for(int i=1;i<=pct;i++) ans=min(ans,f[i][(1<<K)-1]); 62 return ans; 63 } 64 65 int main(){ 66 //freopen("","r",stdin); 67 srand(19260817); 68 for(int T=rd();T;T--){ 69 pct=0,C=0; 70 N=rd(),M=rd(),K=rd(); 71 for(int i=1;i<=N;i++){ 72 for(int j=1;j<=M;j++) id[i][j]=++pct,pos[pct][0]=i,pos[pct][1]=j; 73 } 74 for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) c[id[i][j]]=rd(),C=max(C,c[id[i][j]]); 75 for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) a[id[i][j]]=rd(); 76 int ans1=1e9,ans2=1e9; 77 for(int t=1;t<=233;t++){ 78 for(int i=1;i<=C;i++) hsh[i]=rand()%K; 79 int l=0,r=1e6,a1=1e9,a2=1e9; 80 while(l<=r){ 81 int m=(l+r)>>1; 82 for(int i=1;i<=pct;i++) val[i]=(c[i]==-1?1e8:1000+(a[i]>m)); 83 int re=solve(); 84 if(re>=1e8) break; 85 a1=re/1000; 86 int x=a1-(re-a1*1000); 87 if(x>=(a1+1)/2) a2=m,r=m-1; 88 else l=m+1; 89 } 90 if(a1<ans1||(ans1==a1&&a2<=ans2)) ans1=a1,ans2=a2; 91 } 92 93 printf("%d %d\n",ans1==1e9?-1:ans1,ans1==1e9?-1:ans2); 94 } 95 return 0; 96 }