UVALive 4361 Tobo or not Tobo

本文探讨了如何通过预处理所有可能的状态,并计算从初始状态到任意状态所需的最小步数,适用于九宫格状态转换问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
   As it's only 9^9 status at most(in fact, it's not that much),
   We can calculate all the status,
   which can be reached from initial status 123456789 and
   the number of steps not larger than 9, in advance.
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cctype>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
//STL-Alias
#define UN(c, a) unique(c, a)
#define MS(c, a) memset(c, a, sizeof c)
#define FLC(c, a ,b) fill(c, c + a, b)
#define LOS(c, a, b) lower_bound(c, a, b)
#define UPS(c, a, b) upper_bound(c, a, b)
//Syntax-Alias
#define Rep(c, a, b) for (int c = (a); c < (b); c++)
#define Nre(c, a, b) for (int c = (a); c > (b); c--)
//B-OP
#define LM(x, y) ((x) << (y))
#define RM(x, y) ((x) >> (y))
#define GB(x, y) (RM(x, y) & 1)
#define SB(x, y) (LM(1, y) | x)
#define SBI(x, a, b) ((LM(1, b) - LM(1, a)) | x)
#define CBI(x, a, b) (~(LM(1, b) - LM(1, a)) & x)
//DEBUG
#define FK puts("Fu*k here!")
#define PA(s, c, a, b, p, f){\
	printf(s);\
	Rep(c, a, b) printf(p, (f));\
	puts("");}
//Constant
#define MOD (1000000000LL)
#define MAXN (1 << 16)
//Type-Alias
typedef long long LL;
typedef long double LD;
typedef int AI[MAXN];
typedef double AD[MAXN];
typedef LL ALL[MAXN];
typedef LD ALD[MAXN];


//H[s] as Minimum steps to state s 
map<LL, int> H; 
//Four kinds of rotate
int mr[4][4] = {{0, 1, 4, 3}, {1, 2, 5, 4}, {3, 4, 7, 6}, {4, 5, 8, 7}}; 
//Encode
int EC(int b[3][3])
{
	int s = 0;
	Rep(i, 0, 3) Rep(j, 0, 3)
		s = s * 10 + b[i][j];
	return s;
}
//Decode
void DC(int s, int b[3][3])
{
	Nre(i, 2, -1) Nre(j, 2, -1)
	{
		b[i][j] = s % 10;
		s /= 10;
	}
}
//Rotate function, d indicate direction
int rot(LL s, int *m, int d)
{
	int cp = 0, x = m[cp] / 3, y = m[cp] % 3, b[3][3];
	DC(s, b);
	int t = b[x][y];
	Rep(j, 1, 4)
	{
		int np = (cp + d + 4) % 4, tx = m[np] / 3, ty = m[np] % 3;
		b[x][y] = b[tx][ty];
		cp = np;
		x = tx;
		y = ty;
	}
	b[x][y] = t;
	return EC(b);
}
//Pretreatment 
void H_ini()
{
	H.clear();
	queue<LL> Q;
	LL u = 123456789;
	H[u] = 1;
	Q.push(u);
	while (!Q.empty())
	{
		u = Q.front(); Q.pop();
		if (H[u] > 8) continue;
		Rep(i, 0, 4) Rep(j, -1, 2)
		{
			LL v = rot(u, mr[i], j);
			if (!H[v])
			{
				H[v] = H[u] + 1;
				Q.push(v);
			}
			j++;
		}
	}
}


LL s;


int main()
{
#if 1
	freopen("test.txt", "r", stdin);
#endif
	//Initialize
	int Cas = 1;
	H_ini();
	//Solve
	while (scanf("%lld", &s), s)
	{
		printf("%d. ", Cas++);
		LL p = s / MOD;
		s %= MOD;
		if (H[s] && H[s] - 1 <= p) printf("%d\n", H[s] - 1);
		else puts("-1");
	}
	return 0;
}


<think>好的,我现在需要解决用户的问题:如何通过泛型在基类中封装DTO与BO之间的转换逻辑以实现业务处理的规范性。用户提到参考了一些引用内容,特别是引用[3]中的@MappedSuperClass和引用[2]中的领域模型POJO。我需要结合这些信息,设计一个合理的解决方案。 首先,用户的目标是将DTO到BO的转换逻辑抽象到基类中,使用泛型来实现规范处理。这意味着基类需要能够处理不同子类的DTO和BO类型。泛型在这里可以用于指定具体的DTO和BO类型,子类继承基类时传入相应的类型参数。 接下来,我需要考虑转换方法。通常,对象转换可以使用手动赋值,或者工具库如ModelMapper、MapStruct。但为了保持基类的独立性和减少依赖,可能需要定义抽象方法让子类实现具体的转换逻辑。或者,基类提供通用方法,子类按需覆盖。 然后,参考引用[3]中的@MappedSuperClass,这可能是指基类作为映射的父类,子类继承其映射配置。类似地,在转换逻辑中,基类可以定义通用的转换方法,子类继承并指定类型。例如,定义一个BaseConverter<T, R>,其中T是DTO类型,R是BO类型,基类中包含toBO和fromBO方法,子类实现具体的转换细节。 另外,引用[2]提到DTO和BO属于领域模型POJO,通常只有setter/getter,没有业务逻辑。因此,转换逻辑应该放在基类或工具类中,而不是POJO内部。这样符合分层架构,保持POJO的纯洁性。 用户可能还希望转换逻辑能够复用,避免每个子类重复编写相同的代码。所以基类中可能需要一些公共方法,或者利用反射机制自动映射字段,但反射可能影响性能。因此,或许采用模板方法模式,基类定义流程,子类实现具体步骤。 另外,考虑到类型安全,泛型参数应该严格定义。例如,基类可以是这样的结构: public abstract class BaseService<D extends BaseDTO, B extends BaseBO> { public B convertToBO(D dto) { // 实现转换逻辑,或者调用抽象方法由子类实现 } public D convertToDTO(B bo) { // 类似地 } } 子类继承时指定具体的DTO和BO类型: public class UserService extends BaseService<UserDTO, UserBO> { @Override public UserBO convertToBO(UserDTO dto) { // 具体转换代码 } } 但这样每个子类都需要实现转换方法,可能不够高效。另一种方式是基类提供基于反射或Builder的通用转换,子类只需指定类型。例如,使用BeanUtils.copyProperties,但需要处理字段名不同的情况,或者使用自定义注解指定映射关系。 或者,可以引入一个转换器接口,如GenericConverter<D, B>,基类实现该接口,并让子类提供必要的映射配置。这样更灵活,但可能需要更多的配置。 另外,参考引用[4]中的异常,可能与Spring Kafka相关,但当前问题主要在于泛型和基类设计,可能暂时不需要考虑。但需要注意在转换过程中是否有异步或监听器的问题,比如事务管理或确认机制,但当前场景可能不涉及。 还需要考虑是否使用静态方法或实例方法,基类中的转换方法是否需要访问其他服务或组件,比如依赖注入。如果使用Spring,基类可能需要被继承为Spring管理的bean,但泛型在Spring中的处理可能需要额外的配置。 综合上述思路,可能的解决方案是:定义一个泛型基类,包含转换的抽象方法,子类实现具体转换;或者基类利用工具类进行自动转换,子类只需指定类型。为了提高规范性,可能需要在基类中强制实现转换方法,或者提供默认实现,比如通过反射,但需处理异常情况。 可能的代码结构: public abstract class BaseConverter<D extends BaseDTO, B extends BaseBO> { public abstract B toBO(D dto); public abstract D toDTO(B bo); } 然后业务类继承该基类并实现方法。但用户希望将逻辑封装在基类,减少子类工作。因此,或许基类可以提供通用方法,例如使用ModelMapper: public abstract class BaseService<D, B> { private ModelMapper modelMapper = new ModelMapper(); public B toBO(D dto, Class<B> boClass) { return modelMapper.map(dto, boClass); } public D toDTO(B bo, Class<D> dtoClass) { return modelMapper.map(bo, dtoClass); } } 但这样每次调用都需要传入Class参数,不够方便。或者,在基类中通过泛型获取类型: public abstract class BaseConverter<D extends BaseDTO, B extends BaseBO> { protected Class<D> dtoClass; protected Class<B> boClass; public BaseConverter() { // 通过反射获取泛型参数类型 Type superClass = getClass().getGenericSuperclass(); Type[] types = ((ParameterizedType) superClass).getActualTypeArguments(); dtoClass = (Class<D>) types[0]; boClass = (Class<B>) types[1]; } public B toBO(D dto) { try { B bo = boClass.newInstance(); // 使用BeanUtils或自定义映射逻辑 BeanUtils.copyProperties(dto, bo); return bo; } catch (Exception e) { throw new RuntimeException("转换失败", e); } } // 类似toDTO方法 } 但这种方法可能不够灵活,特别是当字段名称不一致时,需要额外的处理,比如使用注解或者自定义映射配置。例如,引用[3]中的jackson配置使用SNAKE_CASE,可能字段名需要转换,这时候在映射时需要处理命名策略。 因此,可能需要集成ModelMapper,并在基类中配置它,以处理字段名的转换。例如: public abstract class BaseConverter<D, B> { protected ModelMapper modelMapper; public BaseConverter() { modelMapper = new ModelMapper(); // 配置modelMapper,比如字段名策略 modelMapper.getConfiguration() .setFieldMatchingEnabled(true) .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE) .setSourceNameTokenizer(NameTransformers.builder()) .setDestinationNameTokenizer(NameTransformers.builder()); // 添加自定义映射 configureMappings(modelMapper); } protected void configureMappings(ModelMapper modelMapper) { // 子类可以覆盖此方法以添加特定映射 } public B toBO(D dto) { return modelMapper.map(dto, getBOType()); } public D toDTO(B bo) { return modelMapper.map(bo, getDTOType()); } protected abstract Class<B> getBOType(); protected abstract Class<D> getDTOType(); } 这样,子类需要实现getBOType和getDTOType方法,返回具体的类类型。或者,利用TypeToken在基类中获取泛型参数的类型: public abstract class BaseConverter<D, B> { private final Class<D> dtoClass; private final Class<B> boClass; protected ModelMapper modelMapper = new ModelMapper(); @SuppressWarnings("unchecked") public BaseConverter() { Type superClass = getClass().getGenericSuperclass(); ParameterizedType type = (ParameterizedType) superClass; dtoClass = (Class<D>) type.getActualTypeArguments()[0]; boClass = (Class<B>) type.getActualTypeArguments()[1]; } public B toBO(D dto) { return modelMapper.map(dto, boClass); } public D toDTO(B bo) { return modelMapper.map(bo, dtoClass); } } 这样,子类继承时只需指定泛型参数,无需额外代码: public class UserConverter extends BaseConverter<UserDTO, UserBO> { // 可以覆盖configureMappings方法添加自定义映射 } 这种方式利用了ModelMapper进行自动字段映射,减少了子类的代码量。但需要注意字段名称和类型的一致性,或者需要额外的配置来处理特殊情况。例如,引用[2]中提到的DO和DTO可能字段名不同,这时候可以在基类或子类中配置ModelMapper的TypeMap。 此外,引用[3]中的@MappedSuperClass可以应用于基类实体,但这里的场景是DTO和BO的转换,所以可能不需要该注解,除非涉及到JPA实体映射。但用户的问题主要集中在转换逻辑,因此可能不需要该部分。 总结,解决方案步骤: 1. 定义泛型基类,指定DTO和BO的类型参数。 2. 在基类中使用ModelMapper或类似工具处理自动映射。 3. 允许子类覆盖配置以处理特殊字段映射。 4. 子类继承基类,指定具体的DTO和BO类型,必要时添加自定义映射。 这样,转换逻辑被封装在基类中,提高了代码复用和规范性。</think>### 通过泛型基类封装DTO与BO转换逻辑的实现步骤 #### 1. 定义泛型基类 通过泛型参数约束DTO和BO类型,并集成对象映射工具(如ModelMapper)实现通用转换逻辑。 ```java public abstract class BaseConverter<D, B> { protected final ModelMapper modelMapper = new ModelMapper(); private final Class<D> dtoClass; private final Class<B> boClass; @SuppressWarnings("unchecked") public BaseConverter() { // 通过反射获取泛型类型 Type superClass = getClass().getGenericSuperclass(); ParameterizedType type = (ParameterizedType) superClass; dtoClass = (Class<D>) type.getActualTypeArguments()[0]; boClass = (Class<B>) type.getActualTypeArguments()[1]; // 配置映射规则(如字段名策略) modelMapper.getConfiguration() .setFieldMatchingEnabled(true) .setFieldAccessLevel(PRIVATE); } public B toBO(D dto) { return modelMapper.map(dto, boClass); } public D toDTO(B bo) { return modelMapper.map(bo, dtoClass); } } ``` #### 2. 子类继承基类并指定类型 子类只需声明泛型参数,即可复用基类转换逻辑: ```java public class UserConverter extends BaseConverter<UserDTO, UserBO> { // 可扩展自定义映射规则 public UserConverter() { super(); // 添加特定字段映射(例如字段名不一致时) modelMapper.createTypeMap(UserDTO.class, UserBO.class) .addMapping(UserDTO::getUserName, UserBO::setName); } } ``` #### 3. 使用示例 ```java UserDTO userDTO = new UserDTO("张三", "zhangsan@example.com"); UserConverter converter = new UserConverter(); UserBO userBO = converter.toBO(userDTO); // 自动完成DTO→BO转换 ``` #### 4. 高级配置 - **字段名策略**:若DTO与BO字段名遵循特定规范(如蛇形命名法),可在基类中配置: ```java modelMapper.getConfiguration() .setSourceNamingConvention(NamingConventions.SNAKE_CASE) .setDestinationNamingConvention(NamingConventions.LOOSE_PASCAL_CASE); ``` - **自定义类型映射**:子类可覆盖基类方法以处理特殊字段[^3]。 ### 方案优势 1. **规范性**:统一转换入口,避免业务层重复编写映射代码[^2]。 2. **灵活性**:通过泛型支持任意DTO/BO组合,子类可扩展特定规则。 3. **可维护性**:映射逻辑集中管理,修改时只需调整基类或工具配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值