[ZOJ 2960] Re-rejudge [动态规划+状态压缩]

69 篇文章 0 订阅
26 篇文章 0 订阅

现在有一个序列,每个元素是一个集合,集合中可能有p,r,n三种元素。你有5种操作:

1. 删除连续的若干个元素中的p

2. 删除连续的若干个元素中的r

3. 删除连续的若干个元素中的n

4. 直接删除连续的若干个元素

5. 添加一个新元素

其中,前三种操作花费为2,后两种操作花费为1。连续的定义是说,他们在原序列中是挨着的,并且每个元素中都含有对应的元素。

问把原序列变成等长的空集合的序列所需要的最小操作费用。

dp[i][j][k]表示前i个元素变成长度为j的序列,且状态为k的最小操作费用。k代表之前的最后一个操作有没有进行p,r,n,d等操作。d代表删除这个串。

其实不状态压缩也可以..因为要压缩的状态个数是恒定为4个的..跟输入没关系..

但是状态压缩比较好写的样子

#include <cstdio>
#include <cstring>

int dp[510][510][16];
int cal[16][16]={0};
int a[510];
int n;

inline void update(int &a,int b) {
	if (a==-1||a>b) a=b;
}

int main() {
	int i,j,k;
	for (i=0;i<16;i++) 
		for (j=0;j<16;j++) {
			if ((j&1)&&!(i&1)) cal[i][j]+=2;
			if ((j&2)&&!(i&2)) cal[i][j]+=2;
			if ((j&4)&&!(i&4)) cal[i][j]+=2;
			if ((j&8)&&!(i&8)) cal[i][j]++;
		}
	//calculate cal[][]
	while (scanf("%d",&n)!=EOF) {
		for (i=1;i<=n;i++) {
			char s[30];
			scanf("%s",s);
			int tmp=0;
			for (j=0;s[j]!='\0';j++) {
				if (s[j]=='p') tmp|=1;
				else if (s[j]=='r') tmp|=2;
				else if (s[j]=='n') tmp|=4;
			}
			a[i]=tmp;
		}
		int ans=-1;
		memset(dp,-1,sizeof(dp));
		dp[0][0][0]=0;
		for (i=0;i<n;i++) {
			int kk=a[i+1];
			for (j=0;j<n;j++) {
				for (k=0;k<16;k++) {
					if (dp[i][j][k]!=-1) {
						//printf("%d %d %d %d\n",i,j,k,dp[i][j][k]);
						update(dp[i+1][j+1][kk],dp[i][j][k]+cal[k][kk]);
						update(dp[i+1][j][k|8],dp[i][j][k]+cal[k][k|8]);
					}
				}
			}
		}
		for (j=0;j<=n;j++) {
			for (k=0;k<16;k++) {
				if (dp[n][j][k]!=-1) {
					update(ans,dp[n][j][k]+n-j);
				}
			}
		}
		if (ans==0) printf("Impossible!\n");
		else if (ans>200) printf("pia2de4!\n");
		else {
			ans--;
			while (ans--) printf("re-");
			printf("rejudge\n");
		}
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值