zoukankan      html  css  js  c++  java
  • POJ2533&&1836&&3176

    终于写完了POJ的DP专题,然而都是水题233

    这次也把题目分了一下,先挑3道特别简单的讲一下

    2533

    题意:求最长上升子序列。

    很简单,用一般的DP或者二分优化都可以过去

    这里懒得写一般DP了,其实就是用f[i]表示前i个数中LIS的数量,那么在i之前找一个j,满足a[j]<a[j]并且f[j]最大,然后转移即可

    边界条件:f[i]=1

    二分的算法我也有所提及

    二分CODE

    #include<cstdio>
    using namespace std;
    const int N=1005;
    int f[N],top,n,x;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline int find(int x)
    {
    	int l=1,r=top,res=0;
    	while (l<=r)
    	{
    		int mid=l+r>>1;
    		if (f[mid]<x) res=mid,l=mid+1; else r=mid-1;
    	}
    	return res;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i;
    	read(n);
    	for (i=1;i<=n;++i)
    	{
    		read(x);
    		if (!top) { f[++top]=x; continue; }
    		if (x<f[1]) f[1]=x;
    		int now=find(x); top=now+1>top?now+1:top;
    		f[now+1]=x;		
    	}
    	printf("%d",top);
    	return 0;
    }
    

    1836

    题意:类似于合唱队形好吧就是一样的

    给出n个人的身高,要求最少要多少人出列就可以使得所有的人都可以看见两边中的任意一边

    这里我们先处理出从前往后的LIS和从后往前的LIS,然后枚举一下哪两个人之间的人全部出队即可

    CODE

    #include<cstdio>
    using namespace std;
    const int N=1005;
    double a[N];
    int n,back[N],front[N],ans=0;
    inline int max(int a,int b)
    {
    	return a>b?a:b;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i,j;
    	for (scanf("%d",&n),i=1;i<=n;++i)
    	scanf("%lf",&a[i]);
    	for (back[n]=1,i=n-1;i>=1;--i)
    	for (back[i]=1,j=i+1;j<=n;++j)
    	if (a[j]<a[i]) back[i]=max(back[i],back[j]+1);
    	for (front[1]=1,i=2;i<=n;++i)
    	for (front[i]=1,j=1;j<i;++j)
    	if (a[j]<a[i]) front[i]=max(front[i],front[j]+1);
    	for (i=0;i<=n;++i)
    	for (j=i+1;j<=n+1;++j)
    	ans=max(ans,front[i]+back[j]);
    	printf("%d",n-ans);
    	return 0;
    }
    

    3176

    题意:这道题都没有翻译题意,看看样例就知道是老掉牙的数字金字塔问题了

    DP即可,用f[i][j]表示到第i行第j列时最大值是多少,则

    f[i+1][j]=max(f[i+1][j],f[i][j]+a[i][j])
    f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+a[i][j])
    

    CODE

    #include<cstdio>
    using namespace std;
    const int N=360;
    int f[N][N],x,n,ans;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline int max(int a,int b)
    {
    	return a>b?a:b;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i,j;
    	for (read(n),i=1;i<=n;++i)
    	for (j=1;j<=i;++j)
    	read(x),f[i+1][j]=max(f[i+1][j],f[i][j]+x),f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+x);
    	for (j=1;j<=n+1;++j)
    	ans=max(ans,f[n+1][j]);
    	printf("%d",ans);
    	return 0;
    }
    

    当然对于这种DP方程以我的尿性肯定是要滚存一下

    滚存CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=360;
    int f[2][N],x,n,ans;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline int max(int a,int b)
    {
    	return a>b?a:b;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i,j;
    	for (read(n),i=1;i<=n;++i)
    	{
    		int now=i&1,nxt=now^1;
    		memset(f[nxt],0,sizeof(f[nxt]));	
    		for (j=1;j<=i;++j)
    		{
    			read(x); 
    			f[nxt][j]=max(f[nxt][j],f[now][j]+x),f[nxt][j+1]=max(f[nxt][j+1],f[now][j]+x);
    		}
    	}
    	for (j=1;j<=n+1;++j)
    	ans=max(ans,f[(n+1)&1][j]);
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    城市的划入划出效果
    文本溢出省略解决笔记css
    长串英文数字强制折行解决办法css
    Poj 2352 Star
    树状数组(Binary Indexed Trees,二分索引树)
    二叉树的层次遍历
    Uva 107 The Cat in the Hat
    Uva 10336 Rank the Languages
    Uva 536 Tree Recovery
    Uva10701 Pre, in and post
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9028801.html
Copyright © 2011-2022 走看看