STDU 1309:不老的传说问题 区间DP好题

不老的传说问题

题目链接:

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1309

题意:

中文题,和杭电2476挺像的

 

题解:

比较简单,关于k的限制只要在DP的时候加上特判就好了,设dp[i][j]为区间[i,j]内的最少次数,设k点是[i,j-1]中的某一点,则在一般情况下dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j]),这一点应该毫无疑问。那么这里主要就是要特判特殊情况了,也就是当s[k]==s[j]且k到j的距离不超过限制的时候,可以知道dp[i][k-1]不会影响到dp[k][j]的部分,由于s[k]与s[j]相同,因此在刷点 k 的时候可以同时把点 j 也刷了,因此此时dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j])

再考虑第二个条件,涂刷石头是顺时针的,也就是说序列是成环的,那么只需要再创建一个s并接到原来的序列后边,使长度变成原来的双倍,这时候只要求出所有的dp[i][i+n-1]的最小值就好了,比较简单的一道题。

              

代码

#include<stdio.h>
const int N=201;
int s[N*2],dp[N*2][N*2];
int mmin(int x,int y)
{
  return x<y?x:y;
}
void Get_Dp(int n,int mx)
{
  for(int len=0;len<n;++len)
  {
    for(int i=1;i+len<=n;++i)
    {
      int j=i+len;
      dp[i][j]=dp[i][j-1]+1;
      for(int k=i;k<j;++k)
      if(s[j]==s[k]&&j-k+1<=mx)dp[i][j]=mmin(dp[i][j],dp[i][k-1]+dp[k][j-1]);
      else dp[i][j]=mmin(dp[i][j],dp[i][k-1]+dp[k][j]);
    }
  }
}
void solve()
{
  int n,m,k,res;
  while(~scanf("%d%d%d",&n,&m,&k))
  {
    for(int i=1;i<=n;++i)
    scanf("%d",&s[i]),s[i+n]=s[i];
    Get_Dp(n*2,k);
    res=dp[1][n];
    for(int i=1;i<=n;++i)
    if(dp[i][i+n-1]<res)res=dp[i][i+n-1];
    printf("%d\n",res);
  }
}
int main()
{
  solve();
  return 0;
}

posted @ 2016-08-11 15:36  kiuhghcsc  阅读(142)  评论(0编辑  收藏  举报