• [CF1146H]Satanic Panic(dp)


    题面

    http://codeforces.com/contest/1146/problem/H

    题解

    由于五角星难以统计,并且一个五角星唯一对应它的外接五边形,考虑统计原图中凸五边形的数量。

    设dp(i,j,k)表示从i号点开始,走到j号点结束,一共经过k个点,且经过的所有点顺次连接形成的路径为向量i->j右侧的凸包的方案数。

    初始时,所有的dp(i,i,1)为1,其他为0。将图中所有的有向线段按极角升序排序,然后顺次枚举;设当前枚举到的有向线段是由第u号点连向第v号点的,那么枚举i,j,并进行转移dp(i,v,j+1) += dp(i,u,j)。极角排序的好处是不会破坏凸性,此式得以成立。

    最终对所有dp(i,i,6)求和即可。

    时间复杂度(O(n^3))

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define ll long long
    #define rg register
    #define In inline
    
    const ll N = 300;
    
    typedef pair<ll,ll>pll;
    
    In ll read(){
    	ll s = 0,ww = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-')ww = -1;ch = getchar();}
    	while('0' <= ch && ch <= '9'){s = 10 * s + ch - '0';ch = getchar();}
    	return s * ww;
    }
    
    struct vec{
    	ll x,y;
    	vec(){}
    	vec(ll _x,ll _y){x = _x,y = _y;}
    	In friend vec operator - (vec a,vec b){
    		return vec(a.x - b.x,a.y - b.y);
    	}
    	In friend ll Cross(vec a,vec b){
    		return a.x * b.y - a.y * b.x;
    	}
    	In friend bool InUpper(vec a){
    		return a.y > 0 || (a.y == 0 && a.x > 0);
    	}
    }p[N+5];
    
    In bool cmp(pll i,pll j){ //极角排序
    	vec a = p[i.second] - p[i.first],b = p[j.second] - p[j.first];
    	bool k1 = InUpper(a),k2 = InUpper(b);
    	if(k1 != k2)return k1 < k2;
    	return Cross(a,b) > 0;
    }
    
    ll f[N+5][N+5][7];
    ll n;
    pll seg[N*N+5];
    
    int main(){
    	n = read();
    	for(rg int i = 1;i <= n;i++){
    		ll x = read(),y = read();
    		p[i] = vec(x,y);
    	}	
    	int cnt = 0;
    	for(rg int i = 1;i <= n;i++)
    		for(rg int j = 1;j <= n;j++)if(i != j)seg[++cnt] = make_pair(i,j);
    	sort(seg + 1,seg + cnt + 1,cmp);
    	for(rg int i = 1;i <= n;i++)f[i][i][1] = 1;
    	for(rg int k = 1;k <= cnt;k++){
    		int u = seg[k].first,v = seg[k].second;
    		for(rg int i = 1;i <= n;i++)
    			for(rg int j = 1;j <= 5;j++)f[i][v][j+1] += f[i][u][j];
    	}	
    	ll ans = 0;
    	for(rg int i = 1;i <= n;i++)ans += f[i][i][6];
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    js禁止页面回退,刷新,右键代码
    asp.net网站中的Gridview循环判断数据是否被选中
    Gridview中同时选中并删除多个数据
    asp.net中在后台更换控件图片的代码
    关于gcd的8题
    flash AIR 通过BitmapData生成图片到android Camera相册
    flash AIR 通过BitmapData生成图片到本地
    C的随机数
    xcode svn设置事项
    拒绝session丢失 利用DIV层实现对模态窗口的模拟
  • 原文地址:https://www.cnblogs.com/xh092113/p/12365060.html
Copyright © 2020-2023  润新知