1605: [Usaco2008 Open]Crisis on the Farm 牧场危机
Time Limit: 10 Sec
Memory Limit: 64 MB
Submit: 288
Solved: 95
[ Submit][ Status][ Discuss]
Description
约翰和他的奶牛组建了一只乐队“后街奶牛”,现在他们正在牧场里排练.奶牛们分成一堆一堆,共N(1≤N≤1000)堆.每一堆里,30只奶牛一只踩在另一只的背上,叠成一座牛塔.牧场里还有M(1≤M≤1000)个高高的草垛. 作为出色的指挥家,约翰可以通过口哨指挥奶牛们移动.他的口哨有四个音,分别能使所有的牛塔向东南西北四个方向移动一格.
每一次,当一个牛塔到达了一个草垛所在的格子,牛塔最上方的奶牛就会跳到草垛上,而且不再下来,而其他奶牛仍然呈塔状站在草垛所在的格子里.当牛塔只剩一只奶牛时,这只奶牛也会跳到草垛上. 突然,约翰大惊失色:原来邻家的奶缸爆炸了!滚滚而下的牛奶正朝着约翰的牧场冲来,不久就要将牧场淹没.约翰必须马上行动,用口哨声挽救奶牛们的生命.他要指挥奶牛尽量多地跳上草垛,草垛上的奶牛将不会被淹死. 约翰还有K次吹口哨的机会.那他最多还能救多少奶牛呢?请计算最多能挽救的奶牛数,以及达到这个数目约翰需要吹的口哨调子序列.序列用E,W,S,N表示东西南北.如果有多种序列能达到
要求,输出作为字符串最小的.
Input
第1行输入三个整数N,M,K,之后N行每行输入一对整数(Xi,Yi)表示一座牛塔所在的位置,1<=K<=30
之后M行每行输入一对整数(Xi,Yi)表示一个草垛所在的位置.1≤Xi≤1000;1≤Yi≤1000.
Output
第1行输出最多能挽救的奶牛数.第2行输出口哨调子序列.
Sample Input
3 6 3
3 4
6 2
5 7
8 2
9 2
6 4
5 4
6 7
8 7
Sample Output
Use the 'east' whistle three times, at which point the milk floods
the area. Each haystack ends up saving 1 cow.
6
EEE
这题做得实在是。。。。(省略1E9呵呵)
思路嘛就是dp..f[k][i][j]代表吹k下x轴移动i-k,y轴移动j-k的最佳状态,转移不是很难。。
But!!!!!!!!!!!!!!!!
这些牛的位置可以到任意小于0的点或者是大于一千哈哈哈哈哈哈
然后由于我是边做边转移解的状态。。忽略了第一次吹哨,且没拯救牛的情况。。。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 80;
const int dx[4] = {1,0,-1,0};
const int dy[4] = {0,1,0,-1};
const char d[4] = {'W','S','E','N'};
struct W{
char a[maxn];
bool operator < (const W &b) const{
for (int l = 1; l <= maxn; l++)
{
if (a[l] < b.a[l]) return true;
if (a[l] > b.a[l]) return false;
}
}
}w[maxn][maxn][maxn];
struct C{
int x,y;
}cow[1010];
int f[maxn][maxn][maxn],Map[1010][1010],n,m,k,i,j,cnt[maxn][maxn];
bool vis[maxn][maxn][maxn];
int main()
{
//freopen("yzy.txt","r",stdin);
cin >> n >> m >> k;
memset(Map,0,sizeof(Map));
memset(f,0,sizeof(f));
memset(vis,false,sizeof(vis));
for (i = 1; i <= n; i++) scanf("%d%d",&cow[i].x,&cow[i].y);
for (i = 1; i <= m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
Map[x][y] = 1;
}
for (int l = 1; l <= n; l++)
for (i = 0; i <= 2*k; i++)
for (j = 0; j <= 2*k; j++)
{
int xx = cow[l].x + i - k;
int yy = cow[l].y + j - k;
if (xx < 0 || xx > 1000 || yy < 0 || yy > 1000)
{
continue;
}
cnt[i][j] += Map[xx][yy];
}
f[0][k][k] = 0;
vis[0][k][k] = true;
for (int l = 1; l <= k; l++)
for (i = 0; i <= 2*k; i++)
for (j = 0; j <= 2*k; j++)
for (int L = 0; L < 4; L++)
{
int xx = i + dx[L];
int yy = j + dy[L];
if (xx < 0 || xx > 2*k || yy < 0 || yy > 2*k || !vis[l-1][xx][yy]) continue;
vis[l][i][j] = true;
if (f[l][i][j] < f[l-1][xx][yy] + cnt[i][j])
{
f[l][i][j] = f[l-1][xx][yy] + cnt[i][j];
w[l][i][j] = w[l-1][xx][yy];
w[l][i][j].a[l] = d[L];
}
else
if (f[l][i][j] == f[l-1][xx][yy] + cnt[i][j])
{
W K;
K = w[l-1][xx][yy];
K.a[l] = d[L];
if (K < w[l][i][j] || f[l][i][j] == 0) w[l][i][j] = K;
}
}
int ans = -1,I,J;
for (i = 0; i <= 2*k; i++)
for (j = 0; j <= 2*k; j++)
if (f[k][i][j] > ans)
{
ans = f[k][i][j];
I = i; J = j;
}
else
if (f[k][i][j] == ans)
{
if (w[k][i][j] < w[k][I][J])
{
I = i;J = j;
}
}
printf("%d\n",ans);
for (i = 1; i <= k; i++) cout << w[k][I][J].a[i];
return 0;
}