题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1605

题意:

  平面直角坐标系中,有n个点,m个标记(坐标范围1~1000)。

  你可以发出口令,让所有点整体向东、南、西、北四个方向中的任意一个方向移动,口令分别记作'E','S','W','N'。

  每当一个点碰到一个标记,则答案+1。(保证初始时没有点在标记上)

  你最多可以发出t次口令。

  问你答案最大是多少,并输出字典序最小的口令序列。

题解:

  表示状态:

    dp[i][j][k] = max survivors

    i:水平方向共移动了i个单位(左负右正)

    j:竖直方向共移动了j个单位(下负上正)

    k:发了k次口令

    (因为数组下标有负数,所以最后再给i,j统一加上30就好啦,现在先不管它)

  找出答案:

    max dp[i][j][k]

  如何转移:

    先预处理cnt数组:cnt[x][y]表示移动了(x,y)时,碰到标记的点的个数。

    dp[x][y][k] = cnt[x][y] + max dp[lx][ly][k-1]

    lx=i-dx[p], ly=j-dy[p] (p = 0 to 3)

  边界条件:

    dp[0][0][0] = 0

    others = -INF(不存在)

  输出序列:

    说明:

      (1)feas[x][y][k],用来判断最终答案是否由状态(x,y,k)转移而来。

      (2)way[x][y][k],表示在状态(x,y,k)时发出的口令。

    总共三步:

      (1)先将feas全部设为false,再将最终答案的feas改为true。

      (2)枚举k(从大到小),i,j,判断当前(i,j,k)是否能转移到最终答案。如果能,更新当前way和feas。

      (3)枚举k(从小到大),当前位置为(x,y),输出way[x][y][k],并更新(x,y)。

AC Code:

 // state expression:
// dp[i][j][k] = max survivors
// i,j: moving dist
// k: whistling times
//
// find the answer:
// max dp[i][j][t]
//
// transferring:
// dp[x][y][k] = cnt[x][y] + max dp[lx][ly][k-1]
//
// boundary:
// dp[0][0][0] = 0
// others = -INF
//
// find the way:
// if dp[nx][ny][k+1] == cnt[nx][ny] + dp[x][y][k] and feas[nx][ny][k+1]
// way[x][y][k] = c[p]
// feas[x][y][k] = true
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_N 1005
#define MAX_T 65
#define MAX_K 35
#define INF 10000000 using namespace std; const int dx[]={,,,-};
const int dy[]={,,-,};
const char c[]={'E','N','S','W'}; int n,m,t;
int ans=;
int cx[MAX_N];
int cy[MAX_N];
int gx[MAX_N];
int gy[MAX_N];
int cnt[MAX_T][MAX_T];
int dp[MAX_T][MAX_T][MAX_K];
bool feas[MAX_T][MAX_T][MAX_K];
char way[MAX_T][MAX_T][MAX_K]; void read()
{
cin>>n>>m>>t;
for(int i=;i<n;i++)
{
cin>>cx[i]>>cy[i];
}
for(int i=;i<m;i++)
{
cin>>gx[i]>>gy[i];
}
} void cal_cnt()
{
memset(cnt,,sizeof(cnt));
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
int x=gx[j]-cx[i];
int y=gy[j]-cy[i];
if(abs(x)+abs(y)<=t) cnt[x+][y+]++;
}
}
} void cal_dp()
{
for(int k=;k<=t;k++)
{
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
dp[i][j][k]=-INF;
}
}
}
dp[][][]=;
for(int k=;k<=t;k++)
{
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if(i+j->t) continue;
for(int p=;p<;p++)
{
int lx=i-dx[p];
int ly=j-dy[p];
dp[i][j][k]=max(dp[i][j][k],cnt[i][j]+dp[lx][ly][k-]);
}
ans=max(ans,dp[i][j][k]);
}
}
}
} void cal_way()
{
memset(feas,false,sizeof(feas));
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if(dp[i][j][t]==ans) feas[i][j][t]=true;
}
}
for(int k=t-;k>=;k--)
{
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
for(int p=;p<;p++)
{
int nx=i+dx[p];
int ny=j+dy[p];
if(dp[nx][ny][k+]==cnt[nx][ny]+dp[i][j][k] && feas[nx][ny][k+])
{
way[i][j][k]=c[p];
feas[i][j][k]=true;
break;
}
}
}
}
}
} void solve()
{
cal_cnt();
cal_dp();
cal_way();
} void print()
{
cout<<ans<<endl;
int x=;
int y=;
for(int k=;k<t;k++)
{
cout<<way[x][y][k];
for(int p=;p<;p++)
{
if(way[x][y][k]==c[p])
{
x+=dx[p];
y+=dy[p];
break;
}
}
}
} int main()
{
read();
solve();
print();
}

BZOJ 1605 [Usaco2008 Open]Crisis on the Farm 牧场危机:dp【找转移路径】的更多相关文章

  1. BZOJ 1605 [Usaco2008 Open]Crisis on the Farm 牧场危机 DP

    题意:链接 方法: DP 解析: 第一眼搜索题,复杂度不同意dfs,并且牛的数量太多不能bfs,迭代更不可能,A*不会估价.可能记忆化? 等等记忆化我还搜个毛线- 直接改成DP就好了. 状态非常好想非 ...

  2. BZOJ1605 [Usaco2008 Open]Crisis on the Farm 牧场危机

    标题好长&&我是权限狗,汪汪! 题没看懂的我以为这是一道极难滴题目...然后,然后我就看懂题了. 数据少给了一个条件K <= 30...(没这条件还做个鬼...) f[k, i, ...

  3. BZOJ 1621: [Usaco2008 Open]Roads Around The Farm分岔路口

    题目 1621: [Usaco2008 Open]Roads Around The Farm分岔路口 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 56 ...

  4. BZOJ 1621 [Usaco2008 Open]Roads Around The Farm分岔路口:分治 递归

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1621 题意: 约翰的N(1≤N≤1,000,000,000)只奶牛要出发去探索牧场四周的土 ...

  5. bzoj 1621: [Usaco2008 Open]Roads Around The Farm分岔路口【dfs】

    模拟就行--讲道理这个时间复杂度为啥是对的??? #include<iostream> #include<cstdio> using namespace std; int k, ...

  6. bzoj 1231: [Usaco2008 Nov]mixup2 混乱的奶牛 -- 状压DP

    1231: [Usaco2008 Nov]mixup2 混乱的奶牛 Time Limit: 10 Sec  Memory Limit: 162 MB Description 混乱的奶牛 [Don Pi ...

  7. BZOJ 1616 [Usaco2008 Mar]Cow Travelling游荡的奶牛:dp【网格型】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1616 题意: 有一个n*m的网格. '.'表示平坦的草地,'*'表示挡路的树(不能走). ...

  8. bzoj 1609[Usaco2008 Feb]Eating Together麻烦的聚餐【dp】

    设up[i][j]为第i位升序为j的最小修改数,down为降序 #include<iostream> #include<stdio.h> using namespace std ...

  9. bzoj 1616: [Usaco2008 Mar]Cow Travelling游荡的奶牛【dp】

    写了个bfs发现MLE了... 设f[t][i][j]为在t时刻走到(i,j)的方案数,转移和bfs一样 #include<iostream> #include<cstdio> ...

随机推荐

  1. JAVA Eclipse的Android文件结构是怎么样的

    默认res目录下面存放了界面需要的布局和图片文件,之所以图片分为hdpi,ldpi,mdpi这些,是为了不同的设备准备的(高/中/低分辨率的图片)   Bin目录类似于VS的debug或者releas ...

  2. 基于SNMP的交换机入侵的内网渗透

    前言:局域网在管理中常常使用SNMP协议来进行设备的管理和监控,而SNMP的弱点也成为了我们此次渗透的关键. 使用SNMP管理设备只需要一个community string,而这个所谓的密码经常采用默 ...

  3. awakeFromNib方法和viewDidLoad方法区别

    当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作. 也就是说只有通 ...

  4. python实现区块链代码

    如果你明白了原理其实挺简单的. 加密算法是python自带的 需要导入hashlib import hashlib as hash sha = hasher.sha256() sha.update(' ...

  5. ROR部署到Heroku出现Application Error和code=H10 desc=&quot;App crashed“问题

    1.问题发现之前的准备 在读<Learn Python In Hard Way>的时候,发现作者谈到一个非常有趣的事情,在做一些有趣的事情之前做的无聊的事情叫做yak shaving,牦牛 ...

  6. Linux系统运维之路

    九月份开始,半年内搞定运维,博客会慢慢的更新,vim编辑器,Nginx配置文件优化 运维基础 运维基础-Linux发展史.安装.基本操作 运维基础-用户和组管理 运维基础-文件权限管理 运维基础-进程 ...

  7. dede频道标签channel和频道内容标签channelartlist的调用栏目名的不同方式,如果错误使用标签会发生错误

    频道标签 [field:typename/] 频道内容标签 {dede:field name='typename'/}

  8. 【Linux】 awk应用

    1  统计机器上处于不同状态的所有TCP连接的个数(TCP连接是有状态连接,包含SYN_RECV, ESTABLISHED, TIME_WAIT, FIN_WAIT0, FIN_WAIT1等多种状态, ...

  9. 【Python】用Python打开IE、谷歌等浏览器报错及解决办法

    以IE浏览器为例: 当Python Shell输入下面代码时: >>> # coding=utf-8 >>> from selenium import webdri ...

  10. pm2 服务崩溃 Error: bind EADDRINUSE

    pm2 服务崩溃 Error: bind EADDRINUSE  发布于 1 年前  作者 zhujun24  2444 次浏览  来自 问答 Error: bind EADDRINUSE 0.0.0 ...