第四届福建省大学生程序设计竞赛

FZU2140  Forever 0.5

题意:构造一些点使得满足一些条件

思路:把1个点放在(0,0)然后n-1点平均分在60度的圆弧上,这样也就是有n-1对点距离为1.0

因为是60°所以n-1里面有一对点距离是1.0

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#include<queue>
#include<cstring>
#include<set>
#include<stack>
#include<string>
#include<ctime>
#define LL long long
#define maxn 50
#define MAX 700010
#define mod  1000000007
#define INF 0x3f3f3f3f
#define eps 1e-5
using namespace std;
const double pi = acos(-1.0) ;

struct point
{
    double x , y ;
    point(){};
    point( double xx , double yy )
    {
        x = xx ; y = yy ;
    }
} ;
point operator - ( point a , point b )
{
    return point( b.x-a.x , b.y-a.y ) ;
}
double cross( point a  , point b )
{
    return a.x*b.y - a.y*b.x ;
}

int cmp( point a , point b )
{
    return a.y < b.y || a.y == b.y && a.x < b.x ;
}
double get_erea(point *p,int n)
{
    double ans=0;
    for(int i = 1 ; i < n-1 ;i++)
    {
        ans += cross(p[i]-p[0],p[i+1]-p[0]) ;
    }
    return ans/2;
}
double len(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
point Rotate(point a,double rad)
{
    return point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad)) ;
}
void out(point *p,int n )
{
    for( int i = 0 ; i < n ;i++)
        printf("%.6lf %.6lf\n",p[i].x,p[i].y) ;
}
bool check(point *p,int n )
{
    int ans=0,i,j;
    for( i = 0 ; i < n ;i++)
        for( j = i+1 ; j< n;j++)
    {
        double u = len(p[i],p[j]) ;
        if(fabs(u-1.0) <eps)ans++;
        else if(u>1.0) return false;
    }
    if(ans==n) return true;
    return false;
}
int main()
{
    int T,case1=0,n ;
    int i,j,k,u,v,ans;
    point p[110],aa ;
    double rad;
    cin >> T ;
    while(T--)
    {
         scanf("%d",&n) ;
         if(n<=3)
         {
             puts("No");
             continue ;
         }
         p[0].x=0;
         p[0].y=0;
         p[1].x=1;
         p[1].y=0;
         aa=p[1] ;
         rad=pi/3;
         rad /= (n-2);
         for(i = 2 ; i < n ;i++)
         {
            aa=Rotate(aa,rad) ;
            p[i]=aa;
         }
         double ans=get_erea(p,n) ;
        // printf("%.6lf\n",ans) ;
          //   cout<<check(p,n) << endl;
         if(ans+eps>=0.5&&ans<=0.75)
         {
             puts("Yes") ;
             out(p,n) ;
         }
         else puts("No") ;
    }
    return 0;
}

FZU2141 Sub-Bipartite Graph

题意:取出原图的一个子图,这个图是二分图,有至少m/2条边

思路:设二分图的两个部分是A,B,开始所有点在B里面。每次寻找最多度数(去掉A里面的点)的一个点放到A里面,然后判断是否满足要求

没有就继续上面过程。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#include<queue>
#include<cstring>
#include<set>
#include<stack>
#include<string>
#include<ctime>
#define LL long long
#define u64 unsigned long long
#define maxn 100010
#define mod  1000000007
#define INF 1000010
#define eps 1e-5
using namespace std;

vector<int>qe[110],ans ;
int in[110];
bool vi[110] ,hehe[110];

int find(int n)
{
    memset(in,0,sizeof(in)) ;
    for(int i = 1 ; i <= n ;i++)if(!hehe[i])
    {
        for(int j = 0 ; j < qe[i].size();j++)
        {
            int v = qe[i][j] ;
            if(!hehe[v])in[i]++ ;
        }
    }
    int id=INF,Max=0;
    for( int i = 1 ; i <= n;i++)if(!hehe[i])
    {
        if(Max<in[i])
        {
            Max=in[i] ;
            id=i;
        }
    }
    return id;
}
bool check(int n,int m)
{
    int cnt=0;
    for(int i = 1 ; i <= n ;i++)if(hehe[i])
    {
        for( int j = 0 ; j < qe[i].size();j++)
        {
            int v = qe[i][j] ;
            if(!hehe[v])cnt++;
        }
    }
    if(cnt>=m/2) return true;
    return false;
}
int main()
{
    int i,j,n,m,k;
    int u,v,len ,cnt ;
    int T;
    cin >> T ;
    while(T--)
    {
        scanf("%d%d",&n,&m) ;
        ans.clear();
        for( i = 1 ; i <= n ;i++)
        {
            hehe[i]=false;
            qe[i].clear();
        }
        for( i = 1 ; i <= m;i++)
        {
            scanf("%d%d",&u,&v) ;
            qe[u].push_back(v) ;
            qe[v].push_back(u) ;
        }
        len=0;
        while(true)
        {
            k=find(n) ;
            if(k==INF) break ;
            hehe[k]=true;
            ans.push_back(k) ;
            if(check(n,m)) break ;
        }
        cout << ans.size() ;
        for( i = 0 ; i < ans.size();i++)
            cout << " " << ans[i] ;
        puts("") ;
        cout << n-ans.size() ;
        for( i = 1 ; i <= n ;i++)
        {
            if(!hehe[i]){
                    printf(" %d",i) ;
            }
        }
        puts("") ;
    }
    return 0 ;
}

FZU2143 Board Game

题意:不好说

思路:棋盘模型,用最小费用流做。

(a-b)^2 = a*a-2*a*b+b*b,b是常数,忽略。

对于偶数的格子,源点连向它k条边,第i条边的流量为1,花费是 i-1增加到i的代价

也就是 2*i-1-2*b

对于奇数的格子也是一样,不过是它连向汇点

然后奇数格子向相邻的格子连边,代价 0,流量INF

在跑最小费用流的时候,如果dis[t] >= 0 那么就可以退出了,

因为如果加上,那么总的代价就会增加

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#include<queue>
#include<cstring>
#include<set>
#include<stack>
#include<string>
#include<ctime>
#define LL long long
#define u64 unsigned long long
#define maxn 100010
#define mod  1000000007
#define INF 1000010
#define eps 1e-5
using namespace std;

struct node
{
    int u,v,cap,flow,cost,next;
}edge[maxn];
int inf=INF,dis[1010],pre[10010],top;
int head[10010];
bool vis[10010] ;

void add(int u,int v,int cap,int flow,int cost)
{
    edge[top].u = u ;
    edge[top].v = v ;
    edge[top].cap = cap ;
    edge[top].flow = flow ;
    edge[top].cost = cost ;
    edge[top].next = head[u] ;
    head[u]=top++ ;
}
void Unit(int u,int v,int cap,int cost )
{
    //cout<<u<<" "<<v<<endl;
    add(u,v,cap,0,cost);
    add(v,u,0,0,-cost) ;
}
void init()
{
    memset(head,-1,sizeof(head)) ;
    top=0;
}
bool spfa(int s, int t)
{
    queue<int>q;
    // why
    for (int i = 0; i < 1010; i++)
    {
        dis[i] = inf;
        vis[i] = false;
        pre[i] = -1;
    }
    dis[s] = 0;
    vis[s] = true;
    q.push(s);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            if (edge[i].cap > edge[i].flow &&
                    dis[v] > dis[u] + edge[i].cost )
            {
                dis[v] = dis[u] + edge[i].cost;
                pre[v] = i;
                if (!vis[v])
                {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if(dis[t]>=0) return false;////////././.?
    if (pre[t] == -1)return false;
    else return true;
}
int minCost(int s, int t)
{
    int flow = 0;
    int cost = 0;
    while (spfa(s, t))
    {
        int Min = inf;
        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].v])
        {
            if (Min > edge[i].cap - edge[i].flow)
                Min = edge[i].cap - edge[i].flow;
        }
        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].v])
        {
            edge[i].flow += Min;
            edge[i ^ 1].flow -= Min;
            cost += edge[i].cost * Min;
        }
        flow += Min;
    }
   // cout<<cost<<"========"<<endl;
    return cost;
}

int mat[10][10] ,map1[10][10];
int main()
{
    int n,m,i,j,k,ans,s,e;
    int T,case1=0,cnt;
    cin >> T ;
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k) ;
        init();
        ans=cnt=0;
        for( i = 0 ;i < n ;i++)
            for( j = 0 ; j < m ;j++){
             scanf("%d",&mat[i][j]) ;
             ans += mat[i][j]*mat[i][j] ;
             map1[i][j]=++cnt ;
        }
        s = 0 ;
        e = ++cnt ;
        for( i = 0 ; i < n ;i++)
            for( j = 0 ; j < m ;j++)
        {
            for( int u = 1 ; u <= k ;u++)
            {
               if(i%2==j%2) Unit(s,map1[i][j],1,2*u-1-2*mat[i][j]) ;
               else  Unit(map1[i][j],e,1,2*u-1-2*mat[i][j]) ;
            }
            if(i%2==j%2)
            {
                if(i<n-1)Unit(map1[i][j],map1[i+1][j],INF,0) ;
                if(j<m-1)Unit(map1[i][j],map1[i][j+1],INF,0) ;
                if(i>=1)Unit(map1[i][j],map1[i-1][j],INF,0) ;
                if(j>=1)Unit(map1[i][j],map1[i][j-1],INF,0) ;
            }
        }
        printf("Case %d: %d\n",++case1,ans+minCost(s,e)) ;
    }
    return 0 ;
}

FZU 2144 Shooting Game

题意:有n个物体,它出现在一些地方,有一个飞行的方向,速度为1;一个人可以一次袭击把圆里面的所以物体击落

思路:问最少多少次袭击,可以把最多的物品击落。

联立球的方程和直线方程,可以解出 进去时间和出来时间,也就是一个居间

这样就是用最少的点覆盖所有线段问题

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#include<queue>
#include<cstring>
#include<set>
#include<stack>
#include<string>
#include<ctime>
#define LL long long
#define u64 unsigned long long
#define maxn 100010
#define mod  1000000007
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;

struct node
{
    double L,R ;
    bool operator<(const node&s) const
    {
        return R < s.R ;
    }
}qe[maxn] ;

void getnumq(int& x){
    char ch=getchar();
    bool mk=0;
    x = 0;
    while(ch<48 || ch>57){
        if(ch==‘-‘)    mk=1;
        ch=getchar();
    }
    while(ch>=48 && ch<=57){
        x = x*10+ch-48;
        ch = getchar();
    }
    if(mk)    x=-x;
}
void getnum(double& x){
    int y;
    getnumq(y);
    x = y*1.0;
}
int solve(int m)
{
    sort(qe,qe+m) ;
    int ans=0,j;
    for( int i = 0 ; i < m ;i++)
    {
        ans++ ;
        j=i+1;
        while(j<m && qe[j].L <=qe[i].R )
        {
            j++ ;
        }
        i = j-1;
    }
    return ans;
}
int main()
{
    int i,n,m,j,len,T,case1=0;
    double ax,ay,az,dx,dy,dz ;
    double r,a,b,c,d;
    cin >> T ;
    while(T--)
    {
        scanf("%d%lf",&n,&r) ;
        len=0;
        for( j = 1 ; j <= n ;j++ )
        {
            getnum(ax); getnum(ay); getnum(az);
            getnum(dx); getnum(dy); getnum(dz);
            a = dx*dx+dy*dy+dz*dz;
            b = 2*(ax*dx+ay*dy+az*dz);
            c = ax*ax+ay*ay+az*az-r*r;
            d = b*b-4*a*c;
            if(d<0)continue;
            qe[len].L = (b*(-1)-sqrt(d))/(a*2);
            qe[len].R = (b*(-1)+sqrt(d))/(a*2);
            if(qe[len].L<0 && qe[len].R<0)continue;
            len++;
        }
        printf("Case %d: %d %d\n",++case1,len,solve(len)) ;
    }
    return 0 ;
}

FZU 2148 Moon Game

题意:给出n个点,问组成凸四边形的组数

思路:数据很小,枚举。然后判断是否是凸的,

判断大概可以用凸包了......

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#include<queue>
#include<cstring>
#include<set>
#include<stack>
#include<string>
#include<ctime>
#define LL long long
#define maxn 50
#define MAX 700010
#define mod  1000000007
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;

struct point
{
    int x , y ;
    point(){};
    point( int xx , int yy )
    {
        x = xx ; y = yy ;
    }
} ;
point qe[maxn] , p[maxn] ;
point operator - ( point a , point b )
{
    return point( b.x-a.x , b.y-a.y ) ;
}
int cross( point a  , point b )
{
    return a.x*b.y - a.y*b.x ;
}

int cmp( point a , point b )
{
    return a.y < b.y || a.y == b.y && a.x < b.x ;
}
int Get( int n )
{
    sort(qe,qe+n,cmp) ;
    int m = 1 , i , k;
    if( n == 0 ) return 0 ;p[0] = qe[0] ;
    if( n == 1 ) return 1 ;p[1] = qe[1] ;
    if( n == 2 ) return 2 ;p[2] = qe[2] ;
    for( i = 2 ; i < n ;i++)
    {
        while( m && cross( p[m]-p[m-1] , qe[i] - p[m-1] ) <= 0 )m-- ;
        p[++m] = qe[i] ;
    }
    k = m ;p[++m] = qe[n-2] ;
    for( i = n-3 ; i >= 0 ; i-- )
    {
        while( m > k && cross( p[m]-p[m-1] , qe[i]-p[m-1] ) <= 0 )m-- ;
        p[++m] = qe[i] ;
    }
    return m ;
}
int xx[maxn],yy[maxn] ;
int main()
{
    int T,case1=0,n ;
    int i,j,k,u,v,ans;
    cin >> T ;
    while(T--)
    {
         scanf("%d",&n) ;
         for( i = 1 ; i <= n ;i++)
            scanf("%d%d",&xx[i],&yy[i]) ;
         ans=0;
         for( i=1 ; i<= n ;i++)
           for(j=i+1;j<=n;j++)
             for(u=j+1;u<=n;u++)
              for(v=u+1;v<=n;v++)
         {
             qe[0].x=xx[i] ;qe[0].y=yy[i] ;
             qe[1].x=xx[j] ;qe[1].y=yy[j] ;
             qe[2].x=xx[u] ;qe[2].y=yy[u] ;
             qe[3].x=xx[v] ;qe[3].y=yy[v] ;
             k = Get(4) ;
             //cout<<k<<endl;
             if(k==4)ans++;
         }
         printf("Case %d: %d\n",++case1,ans) ;
    }
    return 0;
}

FZU 2150 Fire Game

题意:、

思路:枚举两点,然后dfs;

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#include<queue>
#include<cstring>
#include<set>
#include<stack>
#include<string>
#include<ctime>
#define LL long long
#define maxn 20
#define MAX 700010
#define mod  1000000007
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;

char mat[maxn][maxn] ;
int time1[maxn][maxn] ;
int n,m;

void dfs(int x,int y,int t)
{
    time1[x][y]= t ;
    if(x>1&&mat[x-1][y]==‘#‘&&time1[x-1][y]>t+1)
    {
        dfs(x-1,y,t+1);
    }
    if(y>1&&mat[x][y-1]==‘#‘&&time1[x][y-1]>t+1)
    {
        dfs(x,y-1,t+1);
    }
    if(x<n&&mat[x+1][y]==‘#‘&&time1[x+1][y]>t+1)
    {
        dfs(x+1,y,t+1);
    }
    if(y<m&&mat[x][y+1]==‘#‘&&time1[x][y+1]>t+1)
    {
        dfs(x,y+1,t+1);
    }
}
int solve(int s1,int e1,int s2,int e2)
{

    memset(time1,INF,sizeof(time1)) ;
    dfs(s1,e1,0) ;
    dfs(s2,e2,0) ;
    int ans=-1 ;
    for(int i = 1 ; i <= n ;i++)
        for(int j = 1 ; j <= m ;j++)if(mat[i][j]==‘#‘)
        {
            ans=max(ans,time1[i][j]) ;
        }
        return ans;
}

int getans()
{
    int ans=INF,t;
    for(int i = 1 ; i <= n ;i++)
        for(int j = 1 ; j <= m ;j++)if(mat[i][j]==‘#‘)
    {
        for(int k = i ; k <= n ;k++)
            for(int kk = 1 ; kk <= m ;kk++)if(mat[k][kk]==‘#‘)
        {
            int t = solve(i,j,k,kk) ;
            if(t==-1) t = INF ;
            ans=min(ans,t) ;
        }
    }
    if(ans==INF) return -1;
    return ans;
}

int main()
{
    int T,case1=0 ;
    int i,j,k,ans;
    cin >> T ;
    while(T--)
    {
         scanf("%d%d",&n,&m) ;
         for( i = 1 ; i <= n ;i++)
            scanf("%s",mat[i]+1) ;
         printf("Case %d: %d\n",++case1,getans()) ;
    }
    return 0;
}

时间: 2024-10-28 23:16:50

第四届福建省大学生程序设计竞赛的相关文章

Alice and Bob(2013年山东省第四届ACM大学生程序设计竞赛)

Alice and Bob Time Limit: 1000ms   Memory limit: 65536K 题目描述 Alice and Bob like playing games very much.Today, they introduce a new game. There is a polynomial like this: (a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1). Then Alice as

第八届福建省大学生程序设计竞赛-重现赛

第八届福建省大学生程序设计竞赛-重现赛 B   计算几何 题意:问两个三角形是相交.包含还是相离. tags:套板子..求出相交的面积,再判断一下 /* 多边形相交面积模板 */ #define maxn 510 const double eps=1E-8; int sig(double d){ return(d>eps)-(d<-eps); } struct Point{ double x,y; Point(){} Point(double x,double y):x(x),y(y){} b

sdut Mountain Subsequences 2013年山东省第四届ACM大学生程序设计竞赛

Mountain Subsequences 题目描述 Coco is a beautiful ACMer girl living in a very beautiful mountain. There are many trees and flowers on the mountain, and there are many animals and birds also. Coco like the mountain so much that she now name some letter s

&quot;高教社杯&quot;第三届福建省大学生程序设计竞赛

 A.Problem 2102 Solve equation Accept: 1032    Submit: 2471 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description You are given two positive integers A and B in Base C. For the equation: A=k*B+d We know there always existing many non-

[2013山东省第四届ACM大学生程序设计竞赛]——Alice and Bob

Alice and Bob Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Alice and Bob like playing games very much.Today, they introduce a new game. There is a polynomial like this: (a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1). T

[2013山东省第四届ACM大学生程序设计竞赛]——Rescue The Princess

Rescue The Princess Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Several days ago, a beast caught a beautiful princess and the princess was put in prison. To rescue the princess, a prince who wanted to marry the princess set out immedia

第六届福建省大学生程序设计竞赛不完全题解

昨天自己队做了一下第六届福建省赛,感觉有些蒙,赛后补了几道题,能力有限,一共只出A了7道题 A题   Super Mobile Charger 题目链接 http://acm.fzu.edu.cn/problem.php?pid=2212 水题 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int a[10005]; int b[10005]; int main(

FZU2295 Human life:网络流-最大权闭合子图-二进制优化-第九届福建省大学生程序设计竞赛

目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:Portal传送门 ?原题目描述在最下面. ?题意就是很裸的最大权闭合子图. ?推荐阅读:胡伯涛<最小割模型在信息学竞赛中的应用> ?完完全全的模板题:新疆大学五月月赛-D-勤奋的杨老师 ?本题题意:m(50)个任务,n个技能.完成每个任务由相应的收益,完成每个任务前必须学一些技能.有些技能由先修技能. ?有些任务不能同时完成. Solution: ?训练

(最短路)第七届福建省大学生程序设计竞赛 Problem J- X

Problem Description X is a fully prosperous country, especially known for its complicated transportation networks. But recently, for the sake of better controlling by the government, the president Fat Brother thinks it's time to close some roads in o