UVA 1408 Flight Control

https://vjudge.net/problem/UVA-1408

题目

有个很神奇的雷达,可以得到当前时刻$n\times m$格里面的飞机的能量。每个格子里面任何时间都只会有1架飞机。格子里面的能量反映了飞机的轨迹,飞机是按照能量递减的方向飞行的,只能沿着横向或纵向飞行,并且中途不能改变方向。如果能量为0,表示这个格子里面没有飞过飞机。给出当前的能量图,问从这张图里面能输出最少多少架飞机。

$1\leqslant n\leqslant 50, 1\leqslant m\leqslant 9$

样例输入

3 3
1 2 3
4 5 6
7 8 9

0 0

样例输出

Case 1: 3

题解

训练指南说这是一道入门题= =然后发现我状态设的很差

一开始设状态为当前格子放“<”“>”“^”“v”四种或不放,时间复杂度$5^{n\times m}\times 8$(开头和继续)

然后就不知道怎么优化了

实际上可以剪枝

把开头、不放全部合成成1个“o”,横向“<”“>”合成成“-”,纵向“^”“v”合成成“|”

为了区分继续的方向,可以对三个元素进行判断(这个时候一定有三个元素)

还有一个问题是一个开头只能用一次,不能横向和纵向都接上,因此接纵向的时候判断右边没有接上横向就可以了

AC代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#include<unordered_map>
#define REP(i,a,b) for(register int i=(a); i<(b); i++)
#define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
#define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
using namespace std;
typedef long long ll;
int nrow, ncol;
unordered_map<unsigned, int> dp[57][9];
int mp[57][9];
int kase=0;
inline unsigned setmask(unsigned k, int v, int d) {
	unsigned msk=7<<(v*3);
	k &= ~msk;
	k |= d<<(v*3);
	return k;
}
inline unsigned getmask(unsigned k, int v) {
	return (k>>(v*3))&7;
}
inline bool can(int a, int b, int c) {
	if(a<b && b<c) return true;
	if(a>b && b>c) return true;
	return false;
}
int calc(int r, int c, unsigned F) {
	if(c==ncol) {r++; c=0;}
	if(r==nrow) return 0;
	if(mp[r][c]==0) return calc(r, c+1, setmask(F, c, 0));
	if(dp[r][c].count(F)) return dp[r][c][F];
	int ans=0x3f3f3f3f;
	ans = 1+calc(r, c+1, setmask(F, c, 0));
	
	if(c && mp[r][c-1]) {
		unsigned t=getmask(F,c-1);
		if(t==0 && mp[r][c-1]!=mp[r][c]) {
			ans = min(ans, calc(r, c+1, setmask(F, c, 1)));
		} else if(t==1 && can(mp[r][c-2], mp[r][c-1], mp[r][c])) {
			ans = min(ans, calc(r, c+1, setmask(F, c, 1)));
		}
	}
	if(r && getmask(F,c+1)!=1 && mp[r-1][c]) {
		unsigned t=getmask(F,c);
		if(t==0 && mp[r-1][c]!=mp[r][c]) {
			ans = min(ans, calc(r, c+1, setmask(F, c, 2)));
		} else if(t==2 && can(mp[r-2][c], mp[r-1][c], mp[r][c])) {
			ans = min(ans, calc(r, c+1, setmask(F, c, 2)));
		}
	}
	
	dp[r][c][F]=ans;
	return ans;
}
int main() {
	while(~scanf("%d%d", &nrow, &ncol) && nrow) {
		REP(i,0,nrow) REP(j,0,ncol) {
			scanf("%d", &mp[i][j]);
		}
		REP(i,0,nrow) REP(j,0,ncol) dp[i][j].clear();
		int ans=calc(0,0,0);
		kase++;
		printf("Case %d: %d\n", kase, ans);
		
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/sahdsg/p/12325516.html