zoukankan      html  css  js  c++  java
  • 调整队形「TJOI2007」

    题意

    给定一个初始的序列以及四种操作,问最少操作多少次可以是序列变为回文序列。

    操作如下:

    1. 在队伍左侧或右侧添加一个数

    2. 在队伍中插入一个数

    3. 删除一个数

    4. 改变一个数的值


    思路

    看到给定的序列和改数的操作(其实还是因为询问是最少操作次数),可以想到区间dp。

    设子状态(dp[i][j])表示将区间([i,j])变为回文序列的最少操作次数。

    由于是区间dp,所以2号操作等价于1号操作,而3号操作等价于删除左侧或右侧的数。

    有一个简单的性质:1号操作和3号操作也是等价的。

    这个正确性不难证明:由于添加数和删除数都是为了将没有配对的数配对,所以在效果上是完全一样的。

    于是我们只用考虑两种操作:

    1. 添加/删除数

    2. 改变数值

    对于第一种操作,状态转移方程为

    [f[i][j]=min(f[i][j],min(f[i+1][j],f[i][j-1])+1) ]

    对于第二种操作,状态转移方程为

    [f[i][j]=min(f[i][j],f[i+1][j-1]+1) ]

    注意当左右端点值相等的时候需要特判长度,长度不为2则初始化去掉两端点,若为2则初始化为0。(最后这个点坑了我10分)

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	
    	const int N=3030;
    	
    	int n;
    	int a[N];
    	int dp[N][N];
    
    	inline void MAIN () {
    		read(n);
    		memset(dp,127,sizeof(dp));
    		for (register int i=1; i<=n; ++i) {
    			read(a[i]),dp[i][i]=0;
    		}
    		for (register int len=2; len<=n; ++len) {
    			for (register int l=1,r; l+len-1<=n; ++l) {
    				r=l+len-1;
    				if (a[l]==a[r]&&l+1<=r-1) dp[l][r]=dp[l+1][r-1];
    				if (a[l]==a[r]&&len==2) dp[l][r]=0;
    				dp[l][r]=min(dp[l][r],min(dp[l][r-1],dp[l+1][r])+1);
    				dp[l][r]=min(dp[l][r],dp[l+1][r-1]+1);
    			}
    		}
    		write(dp[1][n]);
    	}
    	
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
    
  • 相关阅读:
    python3----数据结构
    Java的同步容器和并发容器
    Java基础——IO
    JVM(2)——GC算法和收集器
    Java集合(2)——深入理解ArrayList、Vector和LinkedList
    java线程(7)——阻塞队列BlockingQueue
    JVM(1)——简介
    java泛型——基本使用
    java线程(6)——线程池(下)
    java线程(5)——线程池(上)
  • 原文地址:https://www.cnblogs.com/ilverene/p/11689273.html
Copyright © 2011-2022 走看看