poj-3280

22 篇文章 0 订阅
// 16520K	141MS	G++
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

struct OP {
	char valid;
	int addCost;
	int removeCost;
};

const int MAX = 2010;

long DP[MAX][MAX];

typedef struct OP OP;

OP validChar[26];

int M;
int N;

#define INVALID -1 

#define INF 999999999

char str[MAX];

inline long min(long a, long b) {
	return a < b ? a: b;
}

void beginDP() {
	for (int begin = M; begin >=1; begin--) {
		for (int end = begin; end <= M; end++) {
			if (begin == end) { // only on char, no need remove or add 
				DP[begin][end] = 0;
			} else if (begin < end) {
				// 2 char same, no need remove/add
				if (str[begin-1] == str[end-1]) {
					if (begin + 1 == end) {
						DP[begin][end] = 0;
					} else {
						DP[begin][end] = DP[begin+1][end-1];	
					}
				} else {
					char beginChar = str[begin-1];
					char endChar = str[end-1];
					int beginCharPos = beginChar - 'a';
					int endCharPos = endChar - 'a';
					DP[begin][end] = INF;
					// case 1: add end before begin
					long case1Val = INF;
					if (validChar[endCharPos].valid) {
						if (DP[begin][end-1] != -1) {
							DP[begin][end] = min(DP[begin][end-1]
							 	+ validChar[endCharPos].addCost, DP[begin][end]);
						}
					}
					// case 2: add begin after end
					long case2Val = INF;
					if (validChar[beginCharPos].valid) {
						if (DP[begin+1][end] != -1) {
							DP[begin][end] = min(DP[begin+1][end]
							 	+ validChar[beginCharPos].addCost, DP[begin][end]);
						}
					}
					// case 3: remove begin
					long case3Val = INF;
					if (validChar[beginCharPos].valid) {
						if (DP[begin+1][end] != -1) {
							DP[begin][end] = min(DP[begin+1][end]
							 	+ validChar[beginCharPos].removeCost, DP[begin][end]);
						}
					}
					// case 4: remove end
					long case4Val = INF;
					if (validChar[endCharPos].valid) {
						if (DP[begin][end-1] != -1) {
							DP[begin][end] = min(DP[begin][end-1]
							 	+ validChar[endCharPos].removeCost, DP[begin][end]);
						}
					}
					if (DP[begin][end] == INF) {
						DP[begin][end] = -1;
					}
				}
			}
		}
	}
}

void getMinCost() {
	memset(DP, INVALID, sizeof(DP));
	beginDP();
	printf("%ld\n", DP[1][M]);
}

int main() {
	// scanf("%d %d", &N, &M);
	while(scanf("%d %d", &N, &M) != EOF) {
		memset(validChar, 0, sizeof(validChar));
		scanf("%s%*c",str);
		// scanf("%s", str);
		for (int i = 1; i <= N; i++) {
			char Char;
			int addCost;
			int removeCost;
			scanf("%c %d %d%*c", &Char, &addCost, &removeCost);
			int pos = Char - 'a';
			validChar[pos].valid = 1;
			validChar[pos].addCost = addCost;
			validChar[pos].removeCost = removeCost;
		}
		getMinCost();
	}
}

唉,一道简单的DP变形题, 基础就是经典的回文串组成,只不过这次加入了一些限制,只能增加或删除某些字母,

我的code写的是最朴素的逻辑,实际上add和remove在某种意义上是一样的,因此不必分开讨论add和remove, 只保留最小者即可,很多这样的code写的极为简洁,不过无所谓了,我的出发点是以清晰为主,哪怕冗余,就像epp写的书一样。

这道题本身没啥可说,不过犯了一个很低级的错误,导致WA了6,7次......

一开始定义INF时, 考虑到DP数组是long的,于是就搞一个一个超int的数,测试数据OK,提交谁知道竟然WA了,又找了原题的测试数组,发现一个逻辑小问题,就是在

if (str[begin-1] == str[end-1]) {
if (begin + 1 == end) {
DP[begin][end] = 0;
} else {
DP[begin][end] = DP[begin+1][end-1];
}
}

这里没有考虑begin + 1 == end的情况,唉低级错误,在这里mark一下,别再犯。

把原题的数据跑了一遍都OK,提交等AC,谁料又是WA..... , 反复改了几次M范围,输入数据格式啥的,都不管用,

后来,突然发现一点,long和int在32位机上其实长度一样,都是4, 我的机器是64位,因此long是8字节,可以放下INF,而POJ的机器应该是32位的,那么INF必然溢出,就悲剧了......,把INF改小了,就OK了,唉 这种问题也要长心了,不然这种题WA个6,7次,tai

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值