zoukankan      html  css  js  c++  java
  • 3.18 UR17

    打了UOJ Round 17,这么低的分居然还涨rating?!
    T1:
    开始读错题了,1h以后写的暴力过不了样例开始慌,手玩样例发现读错题了,然而并没有时间改,写了子任务123就跑了。
    T2:
    计算几何的气息,直接跳过。
    T3:
    概率期望?看来没得做了。手玩了菊花图的10分,打个表发现其余的跑不出来,弃掉了。
    捆绑测试,有分基本上也都卡没了。

    题解:
    T1:
    最优答案肯定是一条链。
    对于任务34,我们可以直接找最小的,最多log次就会减到最小,复杂度(O(n*log_{2}{n}))
    对于任务5,我们可以枚举一下a[i],设计状态数组f[i]表示在状态i时,变成0最少需要多少代价。
    f[i]=min(f[i],f[i&a[i]]+a[i]),复杂度(O(n*max_w))
    满分做法是我们不枚举a[i],而是枚举一个子集S,找a[]中是否有一个数和它与起来为0.
    这样先预处理a[i]补集的子集就可以了,复杂度是(O(3^{log_{2}max_w}))
    转移方程就变成了(f[i]=min(f[i],f[i^s]+i^s))
    注意可能所有的数与起来不为0,在总的或起来的数异或上它就可以了。

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define int long long 
    #define mmin(a,b) (a<b?a:b)
    int n,f[601000],a[601000];
    bool pd[601000];
    signed main()
    {
    //	freopen("ex_treeand3.in","r",stdin);
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	int all=0,zz=0;
    	for(int i=1;i<=n;i++) all|=a[i];
    	zz=all;
    	for(int i=1;i<=n;i++) zz&=a[i];
    	sort(a+1,a+n+1);
    	for(int i=1;i<=n;i++)
    	{
    		pd[all^a[i]]=1;
    		a[i]^=zz;
    	}
    	all^=zz;
    	pd[0]=1;
    	for(int i=all;i>=0;i--)
    	{
    		if(zz&i) continue;
    		for(int j=0;j<=18;j++)
    		{
    			if(zz&(1<<j)) continue;
    			pd[i]|=pd[i|(1<<j)];
    		}
    	}
    	memset(f,30,sizeof(f));
    	f[0]=0;
    	for(int i=1;i<=all;i++)
    	{
    		if(i&zz) continue;
    		for(int j=i;j;j=(j-1)&i)
    		{
    			if((i^j)>f[i]) break;
    			if(pd[j]) f[i]=mmin(f[i],f[i^j]+(i^j));
    		}
    	}
    	printf("%lld",f[all]+zz*n);
    	return 0;
    }
    

    T2:
    对于一定在端点的情况,我们设状态数组f[i][j],表示一个点为i,另一个点为j时是否能够到达(stx,sty);
    然后二分答案,记忆化一下,复杂度(O(n^2*log_{2}n))
    满分做法:
    仍然是二分答案。
    设状态数组f[i][j]表示一个点在第i个节点,一个点在第j条边上是否合法。
    i和j的最小距离必须小于等于二分的答案v。
    由于把一条直线摆直时,另一条直线一定单调,所以取最小距离就可以了。
    f[i][j]可以有f[k][j]转移过来,k为j的某个端点,j为与i相连的直线;或f[k][j],k与i相连。
    仍然是bfs一下,复杂度(O(n^2*log_{2}n))

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <queue>
    using namespace std;
    #define fang(x) ((x)*(x))
    #define pai pair<int,int>
    struct point{
    	double x,y;
    	int id;
    }q[1010];
    point operator + (const point &s1,const point &s2) {return (point){s1.x+s2.x,s1.y+s2.y};}
    point operator - (const point &s1,const point &s2) {return (point){s1.x-s2.x,s1.y-s2.y};}
    double operator * (const point &s1,const point &s2) {return s1.x*s2.y-s1.y*s2.x;}
    struct line{
    	point a,b;
    }l[1010];
    int n,f[1010][1010],du[1010],stx,sty;
    double eps=1e-7;
    void bfs(double);
    vector<int> ve[1010];
    double getdisxian(point,line);
    double getdisdian(point,point);
    point getpoint(line,line);
    bool check(double);
    signed main()
    {
    //	freopen("in.txt","r",stdin);
    	scanf("%d%d%d",&n,&stx,&sty);
    	for(int i=1;i<=n;i++) scanf("%lf%lf",&q[i].x,&q[i].y),q[i].id=i;
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		l[i].a=q[x]; l[i].b=q[y];
    		if(q[x].x>q[y].x) swap(l[i].a,l[i].b);
    		du[x]++; du[y]++;
    		ve[x].push_back(i);
    		ve[y].push_back(i);
    	}
    	double le=0,ri=2e6;
    	while(ri-le>eps)
    	{
    		double mid=(le+ri)*0.5;
    		bfs(mid);
    		if(check(mid)==1) ri=mid;
    		else le=mid;
    	}
    	printf("%.7f",le);
    	return 0;
    }
    void bfs(double xian)
    {
    	memset(f,0,sizeof(f));
    	if(getdisdian(q[stx],q[sty])>xian) return ;
    	queue<pai> que;
    //	cout<<getdisxian(q[8],l[5])<<endl;
    	for(int i=1;i<=n;i++)
    	{
    		if(du[i]!=1) continue;
    		for(int j=1;j<=n;j++)
    		{
    			if(du[j]==1)
    			{
    				if(getdisdian(q[i],q[j])>xian)
    				{
    					f[i][ve[j][0]]=-1;
    					continue;
    				}
    				if(getdisxian(q[i],l[ve[j][0]])>xian)
    				{
    					f[i][ve[j][0]]=-1;
    					continue;
    				}
    				f[i][ve[j][0]]=1;
    				que.push((pai){i,ve[j][0]});
    			}
    		}
    	}
    	int sz;
    	while(que.empty()==0)
    	{
    		pai x=que.front(); que.pop();
    		sz=ve[x.first].size();
    		for(int i=0;i<sz;i++)
    		{
    			int xi=ve[x.first][i];
    			if(f[l[x.second].a.id][xi]==0)
    			{
    				if(getdisxian(l[x.second].a,l[xi])<xian)
    				{
    					f[l[x.second].a.id][xi]=1;
    					que.push((pai){l[x.second].a.id,xi});
    				}
    				else
    				{
    					f[l[x.second].a.id][xi]=0;
    				}
    			}
    			if(f[l[x.second].b.id][xi]==0)
    			{
    				if(getdisxian(l[x.second].b,l[xi])<xian)
    				{
    					f[l[x.second].b.id][xi]=1;
    					que.push((pai){l[x.second].b.id,xi});
    				}
    				else
    				{
    					f[l[x.second].b.id][xi]=0;
    				}
    			}
    		}
    	}
    }
    double getdisdian(point a,point b)
    {
    	return sqrt(fang(a.x-b.x)+fang(a.y-b.y));
    }
    double getdisxian(point a,line b)
    {
    	point c;
    	if(fabs(b.a.y-b.b.y)<eps) c.x=a.x,c.y=a.y+1;
    	else
    	{
    		double k;
    		if(fabs(b.a.x-b.b.x)<eps) k=0;
    		else k=(b.a.y-b.b.y)/(b.a.x-b.b.x),k=-1.0/k;
    		c.x=a.x+1; c.y=a.y+k;
    	}
    	point d=getpoint((line){a,c},b);
    	if(d.x<=b.b.x&&d.x>=b.a.x) return getdisdian(a,d);
    	else
    	{
    		if(d.x<b.a.x) return getdisdian(a,b.a);
    		else return getdisdian(a,b.b);
    	}
    }
    point getpoint(line a,line b)
    {
    	point p;
    	double dot1=(b.a-a.a)*(b.b-a.a),dot2=(b.b-a.b)*(b.a-a.b);
    	p.x=(a.a.x*dot2+a.b.x*dot1)/(dot1+dot2);
    	p.y=(a.a.y*dot2+a.b.y*dot1)/(dot1+dot2);
    	return p;
    }
    bool check(double xian)
    {
    	if(getdisdian(q[stx],q[sty])>xian) return false;
    	for(int i=0;i<ve[stx].size();i++)
    		if(f[sty][ve[stx][i]]==1)
    			return true;
    	for(int i=0;i<ve[sty].size();i++)
    		if(f[stx][ve[sty][i]]==1)
    			return true;
    	return false;
    }
    

    T3:
    题解和代码都鸽了……

  • 相关阅读:
    2012年"浪潮杯"山东省第三届ACM大学生程序设计竞赛 Fruit Ninja I
    HDU 1045
    ZOJ 3946 Highway Project
    python基础知识
    粘包问题以及解决方法
    socket套接字
    网络编程 互联网协议 tcp原理
    反射 魔法方法 单例模式
    classmethod与staticmethod isinstance与issubclass
    封装 多态
  • 原文地址:https://www.cnblogs.com/hzoi-wangxh/p/8641636.html
Copyright © 2011-2022 走看看