您的位置:首页 > 其它

poj 3671 3670——简单DP

2011-08-01 16:25 330 查看
大意:给你一串只有1,2的数字,让你改变最少的次数,让这个序列变成非递减的。

先开始看这个题目,完全不会做,去网上百度了一下,居然说这个题是求最长非递减子序列的长度,但是用nlogn算法求非严格递增的子序列长度我不会,只能另想办法。在网上搜到了一个神码,我现在都不知道为什么:

#include<cstdio>

int i,n,a,f[3]={0};

int main()

{

scanf("%d",&n);

for(i=0;i<n;++i)

{

scanf("%d",&a),++f[a];

if(f[2]<f[1])f[2]=f[1];

}

printf("%d\n",n-f[2]);

}


后来我自己想了一个。

开一个dp[30010][3]的数组

其中dp[i][j]表示把第i个数改成j最少要花多少次

那么状态转移方程就列出来了:

令a=1 j!=a[i]

0 j==a[i]

那么dp[i][1]=dp[i-1][1]+a;

dp[i][2]=min(dp[i-1][1],dp[i-1][2])+a;

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 30010

int dp[MAXN][3];

int min(int a,int b)
{
return a>b?b:a;
}

int main(void)
{

int n;

scanf("%d",&n);

for(int i=1;i<=n;i++)
{

int a;

scanf("%d",&a);

int b=(a==1?0:1);

dp[i][1]=dp[i-1][1]+b;

b=!b;

dp[i][2]=min(dp[i-1][1],dp[i-1][2])+b;

}

printf("%d\n",min(dp
[1],dp
[2]));

}


poj 3670 也和这个类似,只是有1,2,3数,然后递减也可以:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 30010

int dp[MAXN][4];
int dp2[MAXN][4];

int min(int a,int b)
{
return a>b?b:a;
}

int main(void)
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
int a;
scanf("%d",&a);
int b=(a==1?0:1);
int c=(a==3?0:1);
dp[i][1]=dp[i-1][1]+b;
dp2[i][3]=dp2[i-1][3]+c;
b=(a==2?0:1);
int m=min(dp[i-1][1],dp[i-1][2]);
int n=min(dp2[i-1][3],dp2[i-1][2]);
dp[i][2]=m+b;
dp2[i][2]=n+b;
m=min(m,dp[i-1][3]);
n=min(n,dp2[i-1][1]);
b=(a==3?0:1);
c=(a==1?0:1);
dp[i][3]=m+b;
dp2[i][1]=c+n;
}
int m=min(dp[t][2],dp[t][1]);
m=min(m,dp[t][3]);
int n=min(dp2[t][1],dp2[t][2]);
n=min(n,dp2[t][3]);
printf("%d\n",min(m,n));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: