light oj 1017

来源:互联网 发布:上传淘宝的照片不清晰 编辑:程序博客网 时间:2024/06/03 21:18

题面

题意

有n个点,每一次用刷子刷的时候,可以将w行与x轴平行的点清除,问在k次内最多可以清除几个点.

方法

方法此题的难点就在于如何转移状态,若用纵坐标来,则爆数组,故应该抓住只有n<=100个点,因为一定存在一个最优解中没有两次刷有相交部分,且每次刷的最下面一个点至少有一个点.
因此以最下面的其中一个点来表示怎么刷,并以dp[i][j]表示当前考虑到的最上面的一刷是i,还剩下j次.
所以在写dp时,要根据数据范围较小的点来记录状态

代码

#include<bits/stdc++.h>#define N 110using namespace std;int T,TT,y[N],each[N],last[N],n,w,k,tmp,dp[N][N];//each表示每一刷能刷到的点,last表示最上面与它无相交部分的一刷与它相距的刷数int dfs(int now,int sy){    if(!sy||now<0) return 0;    if(dp[now][sy]!=-1) return dp[now][sy];    dp[now][sy]=max(dfs(now-last[now],sy-1)+each[now],dfs(now-1,sy));    return dp[now][sy];}int main(){    int i,j;    cin>>T;    TT=T;    while(T--)    {        scanf("%d%d%d",&n,&w,&k);        for(i=1;i<=n;i++)        {            scanf("%d%d",&tmp,&y[i]);        }        sort(y+1,y+n+1);        for(i=1;i<=n;i++)        {            for(j=i+1;j<=n;j++)            {                if(y[i]+w<y[j]) break;            }            each[i]=j-i;            for(j=i-1;j>=1;j--)            {                if(y[i]-w>y[j]) break;            }            last[i]=i-j;        }        memset(dp,-1,sizeof(dp));        printf("Case %d: %d\n",TT-T,dfs(n,k));    }}
原创粉丝点击