luogu3888 GDOI2014拯救莫里斯 (状压dp)
题目描述
莫莉斯·乔是圣域里一个叱咤风云的人物,他凭借着自身超强的经济头脑,牢牢控制了圣域的石油市场。
圣域的地图可以看成是一个n*m的矩阵。每个整数坐标点(x , y)表示一座城市\(( 1\le x\le n,1\le y\le m)\)。两座城市间相邻的定义为:对于城市(Ax, Ay)和城市(Bx, By),满足 (Ax - Bx)^2 + (Ay - By)^2 = 1(Ax−Bx)2+(Ay−By)2=1 。
由于圣域的石油贸易总量很大,莫莉斯意识到不能让每笔石油订购单都从同一个油库里发货。为了提高效率,莫莉斯·乔决定在其中一些城市里建造油库,最终使得每一个城市X都满足下列条件之一:
1.该城市X内建有油库,
2.某城市Y内建有油库,且城市X与城市Y相邻。
与地球类似,圣域里不同城市间的地价可能也会有所不同,所以莫莉斯想让完成目标的总花费尽可能少。如果存在多组方案,为了方便管理,莫莉斯会选择建造较少的油库个数。
输入输出格式
输入格式:
第一行两个正整数n,m \(( n \times m \le 50 且 m\le n)\),表示矩阵的大小。
接下来一个n行m列的矩阵F, \(F_{i, j}\) 表示在城市(i,j)建造油库的代价。
输出格式:
输出两个数,建造方案的油库个数和方案的总代价。
其中数据范围是
对于30%数据满足 \(n \times m \le 25\) ;
对于100%数据满足\(n \times m \le 50,0 \le F_{i, j} \le100000\)
看一下这个数据范围,不难得出,m<=7
所以可以直接进行dp
首先我们先预处理一下cost[i][j]表示在第i行,建造j这个状态的油库需要的最小代价是多少
num[j]是j这个状态有几个油库(也就是有几个一) 可以直接用_builtin_popcount()来算
QAQ然后考虑dp
因为第i行的状态只能转移到i+1的状态转移过来
所以f[i][j][k]表示前i-1行的已经都能够合法,第i行的状态是j,第i-1行的状态时k的最小花费
同时g[i][j][k]则表示对应状态的油库数量
首先我们考虑转移条件~~
因为是要求前i行的状态合法,才能转移到i+1
所以要求 \((p| j | k|{j << 1} |{j >> 1}) \&{2^m-1}\ ==\ {2^m
-1}\)
这个条件也就是对应的是第i行是所有的位置都是合法的
然后考虑对于\(f[i][j][k]\)能转移到哪个状态
我们在转移的时候,枚举j,k,p
则
\(f[i+1][p][j]=f[i][j][k]+cost[i+1][p]\)
\(g[i+1][p][j]=g[i][j][k]+num[p]\)
同时当上述的f在转移时相等的时的时候,我们也可以考虑更新g
不懂的可以看一下代码
if (((j|k|p|(j<<1)|(j>>1))&((1 << m)-1))==((1 << m)-1))
{
if (f[i][j][k]+sum[i+1][p]<f[i+1][p][j])
{
f[i+1][p][j]=f[i][j][k]+sum[i+1][p];
g[i+1][p][j]=g[i][j][k]+num[p];
}
else
{
if (f[i][j][k]+sum[i+1][p]==f[i+1][p][j])
{
g[i+1][p][j]=min(g[i+1][p][j],g[i][j][k]+num[p]);
}
QWQ最后的答案就是
f[n+1][0][i] 以及对应最小费用的最小油库个数
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<vector>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 210;
int a[61][61];
int f[61][maxn][maxn];
int g[61][maxn][maxn];
int sum[61][maxn];
int n,m;
int num[maxn];
int ans1=1e9;
int ans2=1e9;
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
a[i][j]=read();
for (int i=1;i<=n;i++)
{
for (int j=0;j<(1 << m);j++)
{
for (int k=1;k<=m;k++)
{
if (j&(1 << (k-1))) {
sum[i][j]+=a[i][k];
}
}
}
}
memset(f,127/3,sizeof(f));
memset(g,127/3,sizeof(g));
for (int j=0;j<(1 << m);j++) num[j]=__builtin_popcount(j);
for (int i=0;i<(1 << m);i++)
{
f[1][i][0]=sum[1][i];
g[1][i][0]=num[i];
}
for (int i=1;i<=n;i++)
{
for (int j=0;j<(1 << m);j++)
for (int k=0;k<(1 << m);k++)
{
for (int p=0;p<(1 << m);p++)
{
if (((j|k|p|(j<<1)|(j>>1))&((1 << m)-1))==((1 << m)-1))
{
if (f[i][j][k]+sum[i+1][p]<f[i+1][p][j])
{
f[i+1][p][j]=f[i][j][k]+sum[i+1][p];
g[i+1][p][j]=g[i][j][k]+num[p];
}
else
{
if (f[i][j][k]+sum[i+1][p]==f[i+1][p][j])
{
g[i+1][p][j]=min(g[i+1][p][j],g[i][j][k]+num[p]);
}
}
}
}
}
}
for (int i=0;i<(1 << m);i++)
{
if (ans1>f[n+1][0][i])
{
ans1=f[n+1][0][i];
ans2=g[n+1][0][i];
}
else
{
if (ans1==f[n+1][0][i])
ans2=min(ans2,g[n+1][0][i]);
}
}
cout<<ans2<<" "<<ans1;
return 0;
}
这大概是QWQ第一篇makedown的博客 嗯
luogu3888 GDOI2014拯救莫里斯 (状压dp)的更多相关文章
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
- [NOIP2016]愤怒的小鸟 D2 T3 状压DP
[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...
- 【BZOJ2073】[POI2004]PRZ 状压DP
[BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...
- bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)
数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...
- HDU 1074 Doing Homework (状压dp)
题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
- 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP
[BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...
- 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP
[BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...
随机推荐
- go-Gorm
软删除 如果模型中有 DeletedAt 字段,它将自动拥有软删除的能力!当执行删除操作时,数据并不会永久的从数据库中删除,而是将 DeletedAt 的值更新为当前时间.
- tensorflow saver简介+Demo with linear-model
tf.train.Saver提供Save和Restore Tensorflow变量的功能,常用于保存.还原模型训练结果,这在自己的训练和迁移学习中都很有用. 训练.保存脚本: import tenso ...
- C++小坑汇总
std::vector::end, 是构想的下一个push_back位置,并不实际指向vector中任何元素. Returns an iterator referring to the past-th ...
- Django的基本运用(垃圾分类)
title: 利用Django实现一个能与用户交互的初级框架 author: Sun-Wind date: September 1, 2021 Django实现基本的框架 此框架的功能是搭建服务器,使 ...
- linux centos7 命令中的 2>&1 代表的意义
2021-09-01 1. 参数介绍 0 – stdin (standard input) 标准输入1 – stdout (standard output) 标准输出2 – stderr (stand ...
- SpringBoot 属性配置文件数据注入配置和yml与properties区别
前言 我们知道SpringBoot 通过配置类来解放一堆的xml文件配置,通属性配置文件,来进行,系统全局属性配置,这样极大的简化了我们开发过程,java web 也可以甜甜的从此 快速配置 Spri ...
- Redis的配置文件redis.conf的解析
1.redis的配置文件为redis.conf 2.redis配置文件redis.conf中关于网络的配置 3.redis配置文件redis.conf中的日志配置 4.redis配置文件redis.c ...
- FastReport合并多份报表为一份预览打印
效果 比较简单,直接贴代码 //打印第一份报表 procedure TForm1.Button2Click(Sender: TObject); begin frxReport1.LoadFromFil ...
- ABP 极简入门教程(一)
本示例不讲概念,只讲怎么用,概念性的内容没有比官方文档更清楚的了,我也正在学习,可能理解的地方有不对的欢迎一起交流,但需要您了解以下内容才能看明白 asp.net core Entity Framew ...
- python库--tensorflow--io操作
方法 返回值类型 参数 说明 .train.Saver() 实例s var_list=None 指定被保存和恢复的变量 dict: {name: 变量} list: [变量] None: 所有save ...