UVa 4787

WF题果然不一样,本来想暴力搜索,数据太大了,数组都开不了。看题解也不太懂,记录一下书上的题解,以后再看:

  此题是给出N*M的格子,有些地方是墙,不可走。求所有不能只通过向上或者向右走而走到右上角的格子。

  通过观察数据,可以发现房间的规模很大(1<=m,n<=1e6),而墙数很小(0<=w<=1000),所以可以先进行离散化。离散化的时候,采用动态规划进行处理,计算的顺序为由上而下、由右而左。设F[i][j]为格子(i,j)能否走到右上角的标志。状态转移方程:F[i][j]={false,(i,j)格为墙;F[i+1][j]||F[i][j+1],(i,j)格非墙}

  最后统计F[i][j]为false且(i,j)非墙的格子数。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = ;//墙数上限
struct Twall//墙的结构类型
{
int x1, x2, y;//行坐标为y,两个端点的列坐标在lx表的指针为x1,x2
};
int n, m, w, n1, m1;//房间规模为n*m,墙数为w
Twall a[MAXN];//墙序列
int lx[MAXN];//存储墙端点的x坐标,表长为n1
long long ans;//被困的格子
bool f[MAXN];//状态转移方程:当前可从lx[i]走至右上角的标志为f[i]
bool g[MAXN];//g[j]=false,表明当前行第j列为被困格 void init()//输入墙的信息
{
ans = (long long)n*m;//初始时所有格子未被困
n1 = ;//lx表长初始化
for (int i = ; i <= w; i++) {//每输入堵墙的两个端点坐标
scanf("%d%d%d%d", &a[i].x1, &a[i].y, &a[i].x2, &a[i].y);
++a[i].x2;
ans -= a[i].x2 - a[i].x1;//被困格子数的初始值为房间中除墙外的格子
lx[++n1] = a[i].x1; lx[++n1] = a[i].x2;//存储第i墙的两个端点的x坐标
}
lx[++n1] = ; lx[++n1] = n;
} void discrete(int a[], int &len)//递增排序数组a,并剔去重复元素
{
sort(a + , a + + len);
int j = ;
for (int i = ; i <= len; i++)
if (a[j] != a[i])
a[++j] = a[i];
len = j;
} int bin(int a[], int len, int k)//在a数组中二分查找值为k的元素下标
{
int l = , r = len, m;
while (l<=r)
{
m = (l + r) >> ;
if (a[m] == k) return m;
if (a[m] < k) l = m + ;
else r = m - ;
}
return -;
} bool cmp_Twall(Twall a, Twall b)//返回同行的a堵墙在b堵墙右方,或者a堵墙在b堵墙上方的标志
{
if (a.y == b.y) return a.x2 > b.x2;
else return a.y > b.y;
} void deal_f(int k)//计算行宽为k时可通过行的格子数,调整被困的格子数
{
long long t = ;
for (int i = ; i < n1; i++)//统计可通行的列宽
if (f[i]) //lx中的第i个x坐标和i+1个x坐标间为一条通向右上角的通道
t += lx[i + ] - lx[i];
ans -= (long long)t*k; //调整被困的格子数
} void solve() //计算和输出被困的格子数
{
discrete(lx, n1); //离散化:递增排序lx数组,并剔去重复元素
for (int i = ; i <= w; i++)//计算每堵墙两端的x坐标在lx中的下标位置
{
a[i].x1 = bin(lx, n1, a[i].x1);
a[i].x2 = bin(lx, n1, a[i].x2);
}
sort(a + , a + + w, cmp_Twall);//按照由右而左、由上而下排序每堵墙
int last = m; //从顶行出发
memset(f, , sizeof(f)); //状态转移方程初始化
f[n1 - ] = true;
int st = , ed; //从a序列的第1堵墙开始分析
while (st<=w) //自上而下分析每堵墙
{
ed = st; //a[st...ed]中的墙位于同一行,且与a[ed+1]不同行
while ((ed < w) && (a[ed + ].y == a[ed].y)) ++ ed;
if (a[st].y != last - ) { //若当前行与前面分析的墙并非相邻行,则计算状态转移方程
for (int i = n1 - ; i >= ; i--)
f[i] = f[i] || f[i + ];
deal_f(last - a[st].y - ); //累计行宽为(last-a[st].y-1)时被困的格子数
}
memset(g, true, sizeof(g));
for (int i = st; i <= ed; i++) //计算a[st..ed]中墙的并集,即当前行被困的格子
for (int j = a[i].x1; j < a[i].x2; j++)
g[j] = false;
f[n1 - ] = f[n1 - ] && g[n1 - ]; //计算状态转移方程
for (int i = n1 - ; i >= ; i--)
f[i] = g[i] && (f[i] || f[i + ]);
deal_f(); //将当前行被困的格子数计入ans
last = a[st].y; //记下当前的行号和下一个不同行的墙序号
st = ed + ;
}
for (int i = n1 - ; i >= ; i--) //计算状态转移方程
f[i] = f[i] || f[i + ];
deal_f(last); //将最后last行中被困的格子数计入ans
printf("%lld\n", ans); //输出被困的格子数
} int main()
{
int CASE = ; //测试编号初始化
while (scanf("%d%d%d",&m,&n,&w)==,!(n==&&m==&&w==))
{
init(); //输入墙的信息
printf("Case %d: ", ++CASE); //输出测试用例编号
solve(); //计算和输出被困的格子数
}
return ;
}

UVALive - 4787 ICPC WF 2010 Tracking Bio-bots【dp】的更多相关文章

  1. UVALive - 6257 K - Chemist's vows 【DFS】【BFS】【DP】

    题目链接 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  2. HDU 5874 Friends and Enemies 【构造】 (2016 ACM/ICPC Asia Regional Dalian Online)

    Friends and Enemies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  3. HDU 5948 Thickest Burger 【模拟】 (2016ACM/ICPC亚洲区沈阳站)

    Thickest Burger Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  4. HDU 5949 Relative atomic mass 【模拟】 (2016ACM/ICPC亚洲区沈阳站)

    Relative atomic mass Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  5. 【转】WF事件驱动

    转自:http://www.cnblogs.com/Mayvar/category/315963.html 这系统的教程有代码可以下载 WF事件驱动(5) 摘要: 之前,我通过4篇文章介绍了在WF4中 ...

  6. HDU 5875 Function 【倍增】 (2016 ACM/ICPC Asia Regional Dalian Online)

    Function Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  7. HDU 5873 Football Games 【模拟】 (2016 ACM/ICPC Asia Regional Dalian Online)

    Football Games Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  8. 【BZOJ2117】 [2010国家集训队]Crash的旅游计划

    [BZOJ2117] [2010国家集训队]Crash的旅游计划 Description 眼看着假期就要到了,Crash由于长期切题而感到无聊了,因此他决定利用这个假期和好友陶陶一起出去旅游. Cra ...

  9. Xenocode Postbuild 2010 for .NET 混淆工具的详细使用步骤【转】

    1,首先我们需要去下载这个工具去,我这里倒是有一个下载的网址,已经被破解了,而且有序列号 http://download.csdn.net/tag/Xenocode+Postbuild+2010+fo ...

随机推荐

  1. LOJ 6042 跳蚤王国的宰相

    LOJ 6042 跳蚤王国的宰相 题意 跳蚤王国爆发了一场动乱,国王在镇压动乱的同时,需要在跳蚤国地方钦定一个人来做宰相. 由于当时形势的复杂性,很多跳蚤都并不想去做一个傀儡宰相,带着宰相的帽子,最后 ...

  2. Django项目:CRM(客户关系管理系统)--32--24PerfectCRM实现King_admin自定义操作数据

    #admin.py # ————————01PerfectCRM基本配置ADMIN———————— from django.contrib import admin # Register your m ...

  3. leetcode 448 - 476

    448. Find All Numbers Disappeared in an Array Input: [4,3,2,7,8,2,3,1] Output: [5,6] 思路:把数组的内容和index ...

  4. Slackware网卡配置文件和配置工具

    Slackware 有关网卡的配置文件是/etc/rc.d/rc.inet1.conf , 这个文件包括乙太网接口的网卡和无线网卡的配置.Slackware 还是比较纯净的,网络配置也较简单:在Sla ...

  5. 洛谷P1006 NOIP提高组2008 传纸条

    P1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无 ...

  6. 开发者必看!探秘阿里云Hi购季开发者分会场:海量学习资源0元起!

    摘要: 开发者分会场致力于帮助开发者学习了解阿里云最新技术,为开发者设计全方位的技术成长与进阶之路. 2019阿里云云上Hi购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: ...

  7. JZOJ 平衡的子集

    Description 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? Input 第 ...

  8. HR招聘_(二)_招聘方法论(招聘原因及原则)

    1 招聘原因 离职 转岗 新增 工作量加大而无法负荷(若为短期工作量的加大可考虑外包或临时雇员) 业务发展需求(新产品线拓展,新事业部组建或组织架构变化等) 2 招聘原则 平等 面试官和候选人双方地位 ...

  9. web服务发展历程

    PhP发展历史1.php: 开始名字含义:personal home page 个人网页 现在名字含义:HyperText Perprocessor 超文本预处理语言 预处理: 说明PHP是在服务器预 ...

  10. CSS-DOM的小知识(一)

    在DOM编程艺术中,CSS-DOM应用很广泛. 1.style属性 通过element.style.property可以获得元素的样式,但是style属性只能够返回内嵌样式,对于外部样式表的样式和he ...