省选模拟赛 LYK loves graph(graph)
题目描述
LYK喜欢花花绿绿的图片,有一天它得到了一张彩色图片,这张图片可以看做是一张n*m的网格图,每个格子都有一种颜色去染着,我们用-1至n*m-1来表示一个格子的颜色。特别地,-1代表这个颜色是黑色,LYK不喜欢黑色!
LYK想将剪下这张图片中的一张子图片来(四联通块),使得这个子图片不存在黑色的格子,并且至少有k个不同的颜色。
但是每个格子有自己的脾气,特别的,第i行第j列这个格子如果被LYK选中了,LYK需要花费相应的代价。LYK想花费尽可能少的代价来剪下一张满足自己要求的图片。
输入格式(graph.in)
第一行三个整数,n,m,k.
接下来n行,每行m个数,表示图片中每个格子的颜色,每个数在-1到n*m-1之间。
接下来n行,每行m个数,表示选择每个位置所需要的代价。
输出格式(graph.out)
一行,表示最小代价和。
输入样例
3 3 3
0 0 1
2 3 3
-1 2 1
3 1 5
4 10 1
9 3 4
输出样例
7
数据范围
对于20%的数据:1<=n,m,k<=4。
对于另外30%的数据:不同的颜色数<=10(不包括-1)。
对于再另外30%的数据:1<=n<=2,1<=m<=15。
对于100%的数据:1<=n,m<=15,1<=k<=7,1<=ai,j<=100000。
数据保证一定有解。
分析:对于前50%的数据,就是一个裸的斯坦纳树. 剩下50%的数据因为颜色数太多,状态表示不下.
注意到k 还是≤7,也就是我们只关注7个不同的颜色. 利用概率性算法,将所有的颜色随机映射到k种颜色中,然后利用前50%的数据的算法. 做一次的成功率是非常低的,多做几次就好了.
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int inf = 0x7ffffff;
const int dx[] = {,,,-},dy[] = {,-,,}; int n,m,k,ans = inf,tot,maxx,block,who,maxn;
int col[][],a[][],flag[][];
int vis[],bb[],f[][][],g[],vis2[][];
bool can[][];
int b[],cnt,Time = ,pos[]; struct node
{
int x,y;
}; void spfa(int sta)
{
queue <node> q;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
{
node temp;
temp.x = i;
temp.y = j;
q.push(temp);
vis2[i][j] = ;
}
}
while (!q.empty())
{
node u = q.front();
q.pop();
int x = u.x,y = u.y;
vis2[x][y] = ;
for (int i = ; i < ; i++)
{
int nx = x + dx[i],ny = y + dy[i];
if (nx >= && nx <= n && ny >= && ny <= m && col[nx][ny] != -)
{
if (f[nx][ny][sta] > f[x][y][sta] + a[nx][ny])
{
f[nx][ny][sta] = f[x][y][sta] + a[nx][ny];
if (!vis2[nx][ny])
{
vis2[nx][ny] = ;
node temp;
temp.x = nx;
temp.y = ny;
q.push(temp);
}
}
}
}
}
} bool check2(int x)
{
int res = ;
while (x)
{
if (x & )
res++;
x >>= ;
}
if (res >= k)
return true;
return false;
} void solve2()
{
tot = ;
memset(vis,,sizeof(vis));
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
{
if (!vis[col[i][j]])
{
bb[col[i][j]] = ++tot;
vis[col[i][j]] = ;
}
}
}
maxx = ( << tot) - ;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
for (int k = ; k <= maxx; k++)
f[i][j][k] = inf;
for (int k = ; k <= maxx; k++)
g[k] = inf;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
f[i][j][ << (bb[col[i][j]] - )] = a[i][j];
}
for (int i = ; i <= maxx; i++)
{
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
for (int l = i; l; l = (l - ) & i)
f[j][k][i] = min(f[j][k][i],f[j][k][l] + f[j][k][l ^ i] - a[j][k]);
spfa(i);
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
g[i] = min(g[i],f[j][k][i]);
}
for (int i = ; i <= maxx; i++)
if (check2(i))
ans = min(ans,g[i]);
printf("%d\n",ans);
} void spfa2(int sta)
{
memset(vis2,,sizeof(vis2));
queue <node> q;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
{
node temp;
temp.x = i;
temp.y = j;
q.push(temp);
vis2[i][j] = ;
}
}
while (!q.empty())
{
node u = q.front();
q.pop();
int x = u.x,y = u.y;
vis2[x][y] = ;
for (int i = ; i < ; i++)
{
int nx = x + dx[i],ny = y + dy[i];
if (nx >= && nx <= n && ny >= && ny <= m && col[nx][ny] != -)
{
if (f[nx][ny][sta] > f[x][y][sta] + a[nx][ny])
{
f[nx][ny][sta] = f[x][y][sta] + a[nx][ny];
if (!vis2[nx][ny])
{
vis2[nx][ny] = ;
node temp;
temp.x = nx;
temp.y = ny;
q.push(temp);
}
}
}
}
}
} void solve()
{
maxx = ( << ) - ;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
for (int k = ; k <= maxx; k++)
f[i][j][k] = inf;
for (int k = ; k <= maxx; k++)
g[k] = inf;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (col[i][j] != -)
f[i][j][ << (pos[col[i][j]] - )] = a[i][j];
}
for (int i = ; i <= maxx; i++)
{
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
for (int l = i; l; l = (l - ) & i)
f[j][k][i] = min(f[j][k][i],f[j][k][l] + f[j][k][l ^ i] - a[j][k]);
spfa2(i);
for (int j = ; j <= n; j++)
for (int k = ; k <= m; k++)
g[i] = min(g[i],f[j][k][i]);
}
for (int i = ; i <= maxx; i++)
{
if (check2(i))
ans = min(ans,g[i]);
}
} int main()
{ scanf("%d%d%d",&n,&m,&k);
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
scanf("%d",&col[i][j]);
if (col[i][j] != -)
b[++cnt] = col[i][j];
}
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
scanf("%d",&a[i][j]);
sort(b + ,b + + cnt);
cnt = unique(b + ,b + + cnt) - b - ;
if (cnt <= )
solve2();
else
{
Time = ;
while (Time--)
{
random_shuffle(b + ,b + + cnt);
for (int i = ; i <= cnt; i++)
pos[b[i]] = ((i - ) % ) + ;
solve();
}
printf(" %d\n",ans);
} return ;
}
省选模拟赛 LYK loves graph(graph)的更多相关文章
- 省选模拟赛 LYK loves rabbits(rabbits)
题目描述 LYK喜欢兔子,它在家中养了3只兔子. 有一天,兔子不堪寂寞玩起了游戏,3只兔子排成一排,分别站在a,b,c这3个位置. 游戏的规则是这样的,重复以下步骤k次:选择两个不同的兔子A和B,假如 ...
- 省选模拟赛 LYK loves string(string)
题目描述 LYK喜欢字符串,它认为一个长度为n的字符串一定会有n*(n+1)/2个子串,但是这些子串是不一定全部都不同的,也就是说,不相同的子串可能没有那么多个.LYK认为,两个字符串不同当且仅当它们 ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- @省选模拟赛03/16 - T3@ 超级树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...
- 3.28 省选模拟赛 染色 LCT+线段树
发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...
- NOI2016模拟赛Zbox loves stack
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- [noi.ac省选模拟赛]第12场题解集合
题目 比赛界面. T1 数据范围明示直接\(O(n^2)\)计算,问题就在如何快速计算. 树上路径统计通常会用到差分方法.这里有两棵树,因此我们可以做"差分套差分",在 A 树上对 ...
- [noi.ac省选模拟赛]第11场题解集合
题目 比赛界面. T1 比较简单.容易想到是求鱼竿的最大独立集.由于题目的鱼竿可以被分割为二分图,就可以想到最大匹配. 尝试建边之后会发现边的数量不小,但联系题目性质会发现对于一条鱼竿,它 ...
- 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)
一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...
随机推荐
- Hyperledger Fabric 1.1 -- Policy 构成
Policy 规则设计 本文主要是讲解一下在fabric中Policy的规则和写法,让大家有一个初步的认识,本文是基于fabric 1.1版本 Policy Type Policy Type 目前包括 ...
- PytorchZerotoAll学习笔记(四)--线性回归
线性回归 # 导入 torch.torch.autograd的Variable模块import torch from torch.autograd import Variable # 生成需要回归需要 ...
- Paper Reading - Long-term Recurrent Convolutional Networks for Visual Recognition and Description ( CVPR 2015 )
Link of the Paper: https://arxiv.org/abs/1411.4389 Main Points: A novel Recurrent Convolutional Arch ...
- ES6的新特性(6)——正则的扩展
正则的扩展 RegExp 构造函数 在 ES5 中,RegExp构造函数的参数有两种情况. 第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag). var regex = ne ...
- Hybrid APP基础篇(四)->JSBridge的原理
说明 JSBridge实现原理 目录 前言 参考来源 前置技术要求 楔子 原理概述 简介 url scheme介绍 实现流程 实现思路 第一步:设计出一个Native与JS交互的全局桥对象 第二步:J ...
- 基于DPDK的高效数据包捕获技术分析与应用
被NFV的论文折磨了两天,今天上午看了两篇DPDK的综述. 传统的包捕获机制 1. BPF 两个组成部分:转发部分和过滤部分. 转发部分负责从链路层提取数据包并转发给过滤部分. 过滤部分根据过滤规则, ...
- J2EE Oa项目上传服务器出现的乱码解决过程
(= =)搞了许久觉得有必要记下来.. 由于我本地的mysql都设置好了,但是服务器的又不能去改它 毕竟还有其他人要用- -: 所以只能是我建的时候去设置一下了, 首先先建数据库 ,表;; creat ...
- 博弈---巴什博奕(Bash Game)(博弈入门)
巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规 定每次至少取一个,最多取m个.最后取光者得胜. 显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走 ...
- 周总结<5>
周次 学习时间 新编写代码行数 博客量(篇) 学到知识点 12 10 100 1 路由器的设置(ospf协议):网页设计:哈夫曼树(C语言数构) Html案例: <!DOCTYPE html P ...
- 玩下软工项目,第一轮--全局Context的获取,SQLite的建立与增删改查,读取用户通话记录信息
项目的Github地址:https://github.com/ggrcwxh/LastTime 采用基于git的多人协作开发模式 软件采用mvc设计模式,前端这么艺术的事我不太懂,交给斌豪同学去头疼了 ...