zoukankan      html  css  js  c++  java
  • FZOJ 2331 LYK loves graph

    魔改最小斯坦纳树的题。。。

    首先我们发现颜色太多了非常不好处理,一种套路是随机把这些颜色映射到 (k) 种颜色,随机很多次来保证正确性。最后的正确率大概是:

    [1-(1-frac{k!}{k^k})^C ]

    其中 (C) 为随机次数。

    好了现在我们只有 (kle 7) 种颜色了。考虑类似最小斯坦纳树的设状态:设 (f[i][j][s]) 表示包括第 (i) 行第 (j) 列的状态为 (s) 的连通块的最小代价。然后由于是点权所以方程式要稍微变动一下。

    代码:

    #pragma GCC optimize(2)
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<random> 
    
    using namespace std;
    
    mt19937 rnd(0); 
    const int N=20,INF=1<<29;
    int dx[10]={0,-1,0,1,0};
    int dy[10]={0,0,1,0,-1};
    int val[N][N],n,m,k,col[N][N],ans=INF,D[N*N],a[N][N],vis[N][N],f[N][N][2000];
    priority_queue <pair<int,pair<int,int> > > q; 
    
    void init()
    {
    	scanf("%d %d %d",&n,&m,&k);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			scanf("%d",&a[i][j]);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			scanf("%d",&val[i][j]);
    }
    
    void Dijkstra(int s)
    {
    	memset(vis,0,sizeof(vis));
    	while(!q.empty())
    	{
    		pair<int,int> p=q.top().second;q.pop();
    		if(vis[p.first][p.second])
    			continue;
    		vis[p.first][p.second]=1;
    		for (int i=1;i<=4;i++)
    		{
    			int tx=p.first+dx[i],ty=p.second+dy[i];
    			if(tx<1||ty<1||tx>n||ty>m||col[tx][ty]==-1)
    				continue;
    			if(f[tx][ty][s]>f[p.first][p.second][s]+val[tx][ty])
    			{
    				f[tx][ty][s]=f[p.first][p.second][s]+val[tx][ty];
    				q.push(make_pair(-f[tx][ty][s],make_pair(tx,ty)));
    			}
    		}
    	}
    }
    
    void work()
    {
    	int T=300;
    	while(T--)
    	{
    		for (int i=0;i<n*m;i++)
    			D[i]=rnd()%k;
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=m;j++)
    				col[i][j]=(a[i][j]!=-1)?D[a[i][j]]:-1;
    		int Max_N=1<<k;
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=m;j++)
    				for (int l=0;l<Max_N;l++)
    						f[i][j][l]=INF;
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=m;j++)
    				if(col[i][j]!=-1)
    					f[i][j][1<<col[i][j]]=val[i][j];
    		for (int s=1;s<Max_N;s++)
    		{
    			for (int i=1;i<=n;i++)
    				for (int j=1;j<=m;j++)
    				{
    					if(col[i][j]==-1) continue;
    					for (int sub=(s-1)&s;sub;sub=(sub-1)&s)
    						f[i][j][s]=min(f[i][j][sub]+f[i][j][s^sub]-val[i][j],f[i][j][s]);
    					if(f[i][j][s]!=INF)
    						q.push(make_pair(-f[i][j][s],make_pair(i,j)));
    				}
    			Dijkstra(s);
    		}
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=m;j++)
    				ans=min(ans,f[i][j][Max_N-1]);
    	}
    	printf("%d
    ",ans==INF?-1:ans);
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    爬取校园新闻首页的新闻的详情,使用正则表达式,函数抽离
    网络爬虫基础练习
    Mysql 使用 select into outfile
    Mysql 使用CMD 登陆
    使用Clean() 去掉由函数自动生成的字符串中的双引号
    Get Resultset from Oracle Stored procedure
    获取引用某个主键的所有外键的表
    Entity Framework 丢失数据链接的绑定,在已绑好的EDMX中提示“Choose Your Data Connection”
    添加MySql Metat Database 信息
    at System.Data.EntityClient.EntityConnection.GetFactory(String providerString)
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13308965.html
Copyright © 2011-2022 走看看