TopCoder SRM 566

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40032278/article/details/82144870

div.1

T1

题意 :

有n个点,m条边,点的位置不知道,但是三点不共线,可以去掉任意条边,问使得没有两条线相交的情况的数量;
思想:
有两种选法,一种是三条边正好围成三角形,另一种是菊花图,这样就保证最长的链长度小于等于2。。。

#include <bits/stdc++.h>
using namespace std;
long long a[100][100],b[100];
class PenguinSledding {
public:
long long countDesigns( int numCheckpoints, vector <int> checkpoint1, vector <int> checkpoint2 ) ;
};
long long sol(long long x,long long y)
{
    long long s=1;
    while(y>0)
    {
        if(y&1) s=s*x;
        x=x*x;
        y=y>>1;
    }
    return s;
}
long long PenguinSledding::countDesigns(int numCheckpoints, vector <int> checkpoint1, vector <int> checkpoint2) {
    long long ans=0;
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    int i,j,k;
    for(i=0;i<checkpoint1.size();i++)
    {
        if(a[checkpoint1[i]][checkpoint2[i]]==0)
        {
            a[checkpoint1[i]][checkpoint2[i]]=a[checkpoint2[i]][checkpoint1[i]]=1;
            b[checkpoint1[i]]++;
            b[checkpoint2[i]]++;
        }
    }
    for(i=1;i<=numCheckpoints;i++)
        for(j=i+1;j<=numCheckpoints;j++)
            for(k=j+1;k<=numCheckpoints;k++)
                if(a[i][j]&&a[j][k]&&a[k][i]) ans++;
    for(i=1;i<=numCheckpoints;i++)
        ans=ans+sol(2,b[i])-1;
    ans-=checkpoint1.size()-1;
    return ans;
}

T2

题意

有一个环,你刚开始在0好点,环上一共有n个点,每天你可以顺时针或逆时针走,在第i天你可以走i步,给出n和天数k,(n<350&&k<1e18),问k天后你在0号点的方案数。

思路

我们考虑在天数大于n后,每天走的步数相当于k%n步,然后这样子我们发现n天一个循环,然后每n天我们走路转移的状态是一样的,我们可以从第n天的状态,推出2n天的状态。。。然后这时我们就可以用快速幂来处理这个k了,复杂度是O(n^2*logk)

#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
class PenguinEmperor {
public:
int countJourneys( int numCities, long long daysPassed ) ;
};
vector<long long> sol(vector<long long> a,vector<long long> b)
{
    int n=a.size(),i,j;
    vector<long long> c(n,0);
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            c[(i+j)%n]=(c[(i+j)%n]+a[i]*b[j])%mod;
    return c;
}
vector<long long> poww(vector<long long> a,long long k)
{
    if(k==0)
    {
        a=vector<long long>(a.size(),0);
        a[0]=1;
        return a;
    }
    if(k%2==0) return poww(sol(a,a),k/2);
    else return sol(a,poww(a,k-1));
}
int PenguinEmperor::countJourneys(int numCities, long long daysPassed) {
    vector<long long> x(numCities,0);
    vector<long long> y(numCities,0);
    x[0]=y[0]=1;
    for(int i=1;i<numCities;i++)
    {
        vector<long long> w(numCities,0);
        w[i]=w[numCities-i]=1;
        x=sol(w,x);
        if(i<=daysPassed%numCities) y=sol(w,y);
    }
    vector<long long> ans=sol(y,poww(x,daysPassed/numCities));
    return (int)ans[0]%mod;
}

div.2

T3

题意

给定n个栅栏每个栅栏与原点的距离都为r,第一个栅栏坐标为(r,0),其余栅栏均匀排布为一正多边形。
现有p个企鹅,你需要通过连线栅栏形成一个封闭图形,将这些企鹅全部包含在内。求此围栏的最小面积,无法完成输出-1。

思路

首先我们先考虑如何判断企鹅和多边形一条边的位置关系。
较为简单的一种方法是考虑直线的方向,如果直线、企鹅成逆时针,则说明在多边形内侧。
判断逆时针可以采用向量的叉积。
而计算最终结果很显然就是一个区间dp了,每次引入的新点带来的面积增量就是个三角形,用向量算算就好了。注意最终点还要检验能否连回第一个点。

#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
const double inf=1e9;
double dp[250][250];
double dx[250],dy[250];
vector<int> X,Y;
class FencingPenguinsEasy
{
    public:
        double calculateMinArea( int numPosts, int radius, vector <int> x, vector <int> y ) ;
};
int check(double x1,double y1,double x2,double y2)
{
    for(int i=0; i<X.size(); i++)
    {
        int x3=X[i],y3=Y[i];
        double t=1.0*(x1-x3)*(y2-y1)-1.0*(y1-y3)*(x2-x1);
        if(t<0) return 0;
    }
    return 1;
}
double sol(double x1, double y1, double x2, double y2, double x3, double y3)
{
    x1=x1-x3;
    y1=y1-y3;
    x2=x2-x3;
    y2=y2-y3;
    return abs((x1*y2-x2*y1)/2.0);
}
double FencingPenguinsEasy::calculateMinArea(int numPosts, int radius, vector <int> x, vector <int> y)
{
    int i,j,k;
    double c=2.0*pi/numPosts,ans=inf;
    for(i=0; i<x.size(); i++) X.push_back(x[i]);
    for(i=0; i<y.size(); i++) Y.push_back(y[i]);
    for(i=0; i<numPosts; i++)
    {
        dx[i]=(radius*cos(c*i));
        dy[i]=(radius*sin(c*i));
    }
    for(i=1; i<numPosts; i++)
        if(!check(dx[i-1],dy[i-1],dx[i],dy[i]))
            return -1.0;
    if(!check(dx[numPosts-1],dy[numPosts-1],dx[0],dy[0]))
        return -1.0;

    for(i=0; i<numPosts; i++)
    {
        for(j=0; j<numPosts; j++)
        {
            if(i==j) dp[i][j]=0;
            else dp[i][j]=inf;
        }
    }


    for(i=1; i<numPosts; i++)
    {
        for(j=i-1; j>=0; j--)
        {
            for(k=j+1; k<=i; k++)
                if(check(dx[j],dy[j],dx[k],dy[k]))
                {
                    dp[j][i]=min( dp[j][i],dp[k][i]+sol(dx[k],dy[k],dx[j],dy[j],dx[i],dy[i]) );
                }
        }
    }
    for(i=0; i<numPosts; i++)
    {
        for(j=i+2; j<numPosts; j++)
        {
            if(check(dx[j],dy[j],dx[i],dy[i]))
                ans=min(ans,dp[i][j]);
        }
    }
    return ans;
}

猜你喜欢

转载自blog.csdn.net/qq_40032278/article/details/82144870