• CF39C Solution


    题目链接

    题目翻译

    给出直线上的 (n) 个圆,圆心坐标为 (c_i)、半径为 (r_i)。如果若干个圆不相交(相离、相切或包含),则称这些圆符合理论。请你求出符合理论圆的最大集合。

    题解

    记录路径鲨我>︿<

    状态(dp[i][j])表示离散化后(最大(2n))的下标([i,j])区间内符合理论的最大圆数。

    转移方程:设(b[i][])为左端点为(i)的圆编号,(cir[i][j])表示是否((1/0))有圆左右端点分别为(i,j)

    [dp[i][j]=min(dp[i+1][j],dp[l][b[i][k]]+dp[b[i][k]][r])+cir[i][j]quad (1le i<jle n) ]

    没有圆以(i)为左端点则取(dp[i+1][j]),否则枚举以(i)为左端点的圆,以其右端点为断点。如果直接枚举断点时间复杂度为(O(n^3)),且易得只有以圆的端点为断点时可以对答案产生影响。

    目标状态(dp[1][cnt])(cnt)为离散化后的下标个数)。

    记录路径(pre[i][j])表示(dp[i][j])选取的断点,若从(dp[i+1][j])转移而来则为(-1)。递归,若存在圆以(i,j)为左右端点则输出该圆编号。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4010;
    int c[N],r[N],qwq[N],a[N],b[N],dp[N][N],pre[N][N],cir[N][N],ans[N],tot,cnt;
    vector<int> s[N];
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	while(ch<'0' || ch>'9') {if(ch=='-') w=-1; ch=getchar();}
    	while(ch>='0' && ch<='9') s=s*10+ch-'0',ch=getchar();
    	return s*w;
    }
    void path(int x,int y)
    {
    	if(cir[x][y]) ans[++tot]=cir[x][y];
    	if(!pre[x][y]) return;
    	if(pre[x][y]==-1) path(x+1,y);	
    	else path(x,pre[x][y]),path(pre[x][y],y);
    }
    int main()
    {
    	int n,x=0;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) 
    	{
    		scanf("%d%d",&c[i],&r[i]);
    		qwq[++cnt]=c[i]-r[i],qwq[++cnt]=c[i]+r[i];
    	}
    	sort(qwq+1,qwq+cnt+1); cnt=unique(qwq+1,qwq+cnt+1)-qwq-1;
    	for(int i=1;i<=n;i++) 
    	{
    		a[i]=lower_bound(qwq+1,qwq+cnt+1,c[i]-r[i])-qwq;
    		b[i]=lower_bound(qwq+1,qwq+cnt+1,c[i]+r[i])-qwq;
    		cir[a[i]][b[i]]=i,s[a[i]].push_back(i);
    	}
    	for(int i=1;i<=cnt;i++)
    	{
    		for(int l=1;l+i<=cnt;l++)
    		{
    			int r=l+i,sz=s[l].size();
    			dp[l][r]=dp[l+1][r],pre[l][r]=-1;
    			for(int k=0;k<sz;k++) 
    			{
    				if(b[s[l][k]]>=r) continue;
    				if(dp[l][b[s[l][k]]]+dp[b[s[l][k]]][r]>dp[l][r]) 
    					dp[l][r]=dp[l][b[s[l][k]]]+dp[b[s[l][k]]][r],pre[l][r]=b[s[l][k]];
    			} 
    			dp[l][r]+=(cir[l][r]>0);
    		}
    	} 
    	path(1,cnt);
    	printf("%d
    ",tot);
    	for(int i=1;i<=tot;i++) printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    elasticsearch
    超人学院课课程体系
    51cto大数据培训路线
    关于举办大数据处理技术培训的通知
    “大数据分析高级工程师”培训
    成都大数据Hadoop与Spark技术培训班
    大数据时代新闻采编人员职业能力培训
    EXCEL常用函数
    大数据实时处理-基于Spark的大数据实时处理及应用技术培训
    Properties vs. Attributes
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14818203.html
Copyright © 2020-2023  润新知