题目链接: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. 跨域问题解决方式(HttpClient安全跨域 &amp; jsonp跨域)

    1 错误场景 今天要把项目部署到外网的时候,出现了这种问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 执行 都没有问题的, 一旦把我须要调用接口的项目B放到其它的server上, ...

  2. Theano学习笔记(四)——导数

    导数使用T.grad计算. 这里使用pp()打印梯度的符号表达式. 第3行输出是打印了经过优化器简化的符号梯度表达式,与第1个输出相比确实简单多了. fill((x** TensorConstant{ ...

  3. Android学习笔记(36):Android的两种事件处理方式

    Android提供了两种事件处理的方式:基于回调的事件处理 和 基于监听的事件处理. 我们来说的easy理解一点: (1)基于回调的事件处理就是继承GUI组件,并重写该组件的事件处理方法.除了一些特定 ...

  4. HTML字体对应word字体

    42磅对应初号. 36磅对应小初. 26磅对应一号. 24磅对应小一号. 22磅对应二号. 18磅对应小二号. 16磅对应三号. 15磅对应小三号. 14磅对应四号. 12磅对应小四号. 10.5磅对 ...

  5. 高阶函数:map()/reduce()

    Python内建了map()和reduce()函数. 如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on Large Clus ...

  6. versions 忽略 xcuserdata 目录

    1.打开versions,选中xcuserdata目录 2.菜单条.Action->ignore "..." 3.versions不再显示不同

  7. vim 处理换行符

    1. 设置文件格式 :set fileformats=unix,dos 2. 查询当前文件格式 :set fileformat? 3. 转换文件格式 :set fileformat=dos 4. 设置 ...

  8. c#中Monitor的使用

    首先lock和Minitor有什么区别呢? 其实lock在IL代码中会被翻译成Monitor.也就是Monitor.Enter(obj)和Monitor.Exit(obj). lock(obj) { ...

  9. Cocoapods完整使用篇

    温馨提示:在篇文章中所使用的Xcode版本为Xcode7.   一.什么是CocoaPods? 简单来说,就是专门为iOS工程提供对第三方库的依赖的管理工具,通过CocoaPods,我们可以单独管理每 ...

  10. iOS开发人员程序许可协议

    请细致阅读以下的许可协议条款和条件之前下载或使用苹果软件.   这些条款和条件构成你和苹果之间的法律协议.   iOS开发人员程序许可协议   目的 你想使用苹果软件(例如以下定义)来开发一个或多个应 ...