您的位置:首页 > 其它

【经典dp】 poj 3671

2014-10-10 10:31 246 查看
开一个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;

那么根据空间优化原理,我们的第一维的i不过是为了递推,那么可以优化掉。

不过要注意的是,dp【2】的状态要先求,否则测试数据会是3,因为沿用了本次的dp【1】,而非上次的dp【1】。

#include <iostream>
#include <cstdio>
#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int maxn=30002;
//int dp[maxn][3];
int dp[maxn];
int cow[maxn];
int main()
{
// freopen("in.txt","r",stdin);
int n;
cin >> n;
for(int i=1;i<=n;i++)
{
cin >> cow[i];
int flag;
if(cow[i]==2)
flag=0;
else flag=1;
//dp[i][2]=min(dp[i-1][1],dp[i-1][2])+flag;
dp[2]=min(dp[1],dp[2])+flag;
if(flag==0)flag=1;
else flag=0;
// dp[i][1]=dp[i-1][1]+flag;
dp[1]=dp[1]+flag;
}
//cout << min(dp
[1],dp
[2])<< endl;
cout << min(dp[1],dp[2])<< endl;
return 0;
}


左右遍历,计算left【i】+right【i】的max:


#include <iostream>
#include <cstdio>
#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
#define maxn 30002
int s[maxn],l[maxn],r[maxn];
int main()
{
//freopen("in.txt","r",stdin);
memset(s,0,sizeof(s));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
int n;
cin >> n;
for(int i=1;i<=n;++i)
{
cin >> s[i];
}
if(s[1]==1)
{
l[1]=1;
}
for(int i=2;i<=n;i++)
{
if(s[i]==1)
{
l[i]=l[i-1]+1;
}
else l[i]=l[i-1];
}
if(s
==2)
{
r
=1;
}
for(int i=n-1;i>=0;i--)
{
if(s[i]==2)
{
r[i]=r[i+1]+1;
}
else r[i]=r[i+1];
}
int max=0;
for(int i=1;i<=n;i++)
{
if(l[i]+r[i]>max)
{
max=l[i]+r[i];
}
}
cout << n-max << endl;
return 0;
}


还有一个不错的方法,我们先计算1的个数,然后从前遍历,每次判断:是2就自加1,不是就自减1,其中保存min,则为结果。实际上也为dp,每次的i值代表,编号为i的数组前面不可更改的数字1个数。


#include <iostream>
#include <cstdio>
using namespace std;
const int MAX=30000+10;
int a[MAX]; //存储输入的串
int main()
{
//freopen("in.txt","r",stdin);
int cnt; //数组元素的个数
int i; int min; //最少要改变的次数
scanf("%d",&cnt);
int num1=0;
for (i=0;i<cnt;i++)
{
scanf("%d",&a[i]);
if (a[i] == 1)
num1++;
} min=num1;
for (i=0;i<cnt;i++)
{
(a[i] == 1) ? num1-- : num1++;
if (min > num1)  min = num1;
}
printf("%d\n",min);
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: