2010福州赛区模拟赛总结

   A题:神题,不解释。

   B题:貌似是最小割,自己暂时不会,先放一下。

  C题:计算几何,凸包和旋转什么的,暂时没做。

  D 题:数位dp,暂时实现不来、

  E题:计算几何,求四边形费马点,输出费马点距离四个顶点的距离和最小值,首先判断是否为凸四边形,假设是,那么费马点为对角线交点,否则为其中某个顶点,

  判断凸四边形,直接做凸包,判断凸包上的点是不是4个,假设不是凸四边形,枚举每个顶点,去最小值。

代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
const double eps=1e-8;
int sgn(double x)
{
       if(fabs(x)<eps)return 0;
       if(x>0)return 1;
       return -1;
}
struct Point
{
       double x,y;
       Point(){}
       Point(double _x,double _y):x(_x),y(_y){}
       Point operator - (const Point &b) const
       {
              return Point (x-b.x,y-b.y);
       }
       Point operator + (const Point &b) const
       {
              return Point (x+b.x,y+b.y);
       }
       double operator ^ (const Point &b) const
       {
              return x*b.y-y*b.x;
       }
       double operator * (const Point &b) const
       {
              return x*b.x+y*b.y;
       }
}p[10];
int Stack[100],top,id;
double dist(Point a,Point b)
{
      return sqrt((a-b)*(a-b));
}
bool cmp(Point p1,Point p2)
{
       double tmp=(p1-p[0])^(p2-p[0]);
       if(sgn(tmp)>0)return 1;
       else if(sgn(tmp)==0&&sgn(dist(p1,p[0])-dist(p2,p[0]))<=0)
              return 1;
       return 0;
}
void Graham(int n)
{
       Point p0;
       int k=0;
       p0=p[0];
       for(int i=1;i<n;i++)
       if(p0.y>p[i].y||(p0.y==p[i].y&&p0.x>p[i].x))
       {
              p0=p[i];
              k=i;

       }
       swap(p[0],p[k]);
       sort(p+1,p+4,cmp);
       if(n==1)
       {
              top=1;
              Stack[0]=0;
              return;
       }
       if(n==2)
       {
              top=2;
              Stack[0]=0;
              Stack[1]=1;
              return;
       }
       Stack[0]=0;
       Stack[1]=1;
       top=2;
       for(int i=2;i<n;i++)
       {
              while(top>1&&sgn((p[Stack[top-1]]-p[Stack[top-2]])^(p[i]-p[Stack[top-2]]))<=0)
                     id=Stack[top],top--;
              Stack[top++]=i;
       }
}
int main()
{
       int i,j,k,m,n;
       while(~scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p[0].x,&p[0].y,&p[1].x,&p[1].y,&p[2].x,&p[2].y,&p[3].x,&p[3].y))
       {
              if(p[0].x==-1&&p[0].y==-1
               &&p[1].x==-1&&p[1].y==-1
               &&p[2].x==-1&&p[2].y==-1
               &&p[3].x==-1&&p[3].y==-1)break;
            Graham(4);
            double ans=100000000;
            if(top==4)
              ans=dist(p[Stack[0]],p[Stack[2]])+dist(p[Stack[1]],p[Stack[3]]);

            else
            {
                   ans=min(ans,dist(p[0],p[1])+dist(p[0],p[2])+dist(p[0],p[3]));
                   ans=min(ans,dist(p[1],p[0])+dist(p[1],p[2])+dist(p[1],p[3]));
                   ans=min(ans,dist(p[2],p[0])+dist(p[2],p[1])+dist(p[2],p[3]));
                   ans=min(ans,dist(p[3],p[0])+dist(p[3],p[1])+dist(p[3],p[2]));
            }
            printf("%.4lf\n",ans);
       }
       return 0;
}

F题:ac自动机模板题,求串里有几个给定的模式串,正向算一次,反向算一次。

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
struct Trie
{
       int next[250010][26],fail[250010],end[250010];
       int L,root;
       int newnode()
       {
              for(int i=0;i<26;i++)
                     next[L][i]=-1;
              end[L++]=0;
              return L-1;
       }
       void init()
       {
              L=0;
              root=newnode();
       }
       void insert(char buf[])
       {
              int len=strlen(buf);
              int now=root;
              for(int i=0;i<len;i++)
              {
                     if(next[now][buf[i]-'A']==-1)next[now][buf[i]-'A']=newnode();
                     now=next[now][buf[i]-'A'];
              }
              end[now]++;
       }
       void build()
       {
              queue<int> q;
              fail[root]=root;
              for(int i=0;i<26;i++)
              {
                     if(next[root][i]==-1)next[root][i]=root;
                     else
                     {
                            fail[next[root][i]]=root;
                            q.push(next[root][i]);
                     }
              }
              while(!q.empty())
              {
                     int now=q.front();
                     q.pop();
                     for(int i=0;i<26;i++)
                     {
                            if(next[now][i]==-1)
                                   next[now][i]=next[fail[now]][i];
                            else
                            {
                                   fail[next[now][i]]=next[fail[now]][i];
                                   q.push(next[now][i]);
                            }
                     }
              }
       }
       int query(char buf[])
       {
              int len=strlen(buf);
              int now=root;
              int res=0;
              for(int i=0;i<len;i++)
              {
                     now=next[now][buf[i]-'A'];
                     int temp=now;
                     while(temp!=root&&end[temp]!=-1)
                     {
                            res+=end[temp];
                            end[temp]=-1;
                            temp=fail[temp];
                     }
              }
              return res;
       }
};
Trie ac;
char buf[5500100];
int main()
{
       int i,j,k,m,n,T;
       scanf("%d",&T);
       while(T--)
       {
              scanf("%d",&n);
              ac.init();
              while(n--)
              {
                     scanf("%s",buf);
                     ac.insert(buf);
              }
              ac.build();
              int j=0;
              getchar();
              char c;
              while(c=getchar(),c!='\n')
              {
               if(c=='[')
               {
                scanf("%d",&n);
                c=getchar();
                for(int i=0;i<n;i++)
                buf[j++]=c;
                getchar();
               }
                else buf[j++]=c;
              }
              buf[j]='\0';
             // cout<<buf<<endl;
              int ans=ac.query(buf);
              reverse(buf,buf+strlen(buf));
              ans+=ac.query(buf);
              printf("%d\n",ans);
       }
}

G题:图论题目。

题意:给定一连串的物品,已知每一个物品的价格,数量,给定一连串允许的交换,求可以得到的最大的价值。

解题思路:(1)可以按照拓扑排序的思路,在拓扑排序时更新一下。

               (2)按照spfa求最长路的思路做,不过没实现。

 思路1代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<stack>
#include<string>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=69930;
int head[maxn],tol,in[maxn];
double p[maxn],q[maxn],n;
struct node
{
       int next,to;
       double val;
}edge[maxn];
void add(int u,int v,double w)
{
       edge[tol].to=v;
       edge[tol].next=head[u];
       edge[tol].val=w;
       head[u]=tol++;
}
void init()
{
       memset(head,-1,sizeof(head));
       tol=0;
       memset(in,0,sizeof(in));
}
int main()
{
       while(cin>>n&&n)
       {
              init();
              for(int i=1;i<=n;i++)
                     cin>>p[i]>>q[i];
              int m;
              cin>>m;
              while(m--)
              {
                     int pre,next,k;
                     double pi;

                     cin>>k>>pre;
                     k--;
                     while(k--)
                     {
                            cin>>pi>>next;
                            add(next,pre,pi);
                            in[pre]++;
                            pre=next;
                     }
              }
             // cout<<tol<<endl;
              double ans=0;
              stack<int> Q;
              for(int i=1;i<=n;i++)
                     if(!in[i])Q.push(i);
                     while(!Q.empty())
                     {
                            int u=Q.top();
                            Q.pop();
                            ans+=p[u]*q[u];
                            for(int i=head[u];i!=-1;i=edge[i].next)
                            {
                                   int v=edge[i].to;
                                   p[v]=max(p[v],p[u]*edge[i].val);
                                   if(--in[v]==0)Q.push(v);
                            }
                     }
                     printf("%.2lf\n",ans);
       }
       return 0;
}

H题:

已知一堆课程的允许选的起始时间,截止时间,一个学生每五分钟选一次,问最大可以选多少门课。

解题思路:把课程按结束时间排序,优先选择早结束的,枚举学生从0-4分开始选课,然后枚举取最大值。

代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<stack>
#include<string>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=500;
int vis[maxn];
struct node
{
       int st,ed;
}pp[500];
bool cmp(node a,node b)
{
       return a.ed<b.ed;
}
int main()
{
       int n;
       while(~scanf("%d",&n)&&n)
       {
              for(int i=0;i<n;i++)scanf("%d%d",&pp[i].st,&pp[i].ed);
              sort(pp,pp+n,cmp);
              int ans=0;
              for(int i=0;i<5;i++)
              {
                     memset(vis,0,sizeof(vis));
                     int ret=0;
                     for(int j=i;j<=1000;j+=5)
                     for(int k=0;k<n;k++)
                     if(!vis[k]&&pp[k].st<=j&&pp[k].ed>j)
                     {
                            vis[k]=1;
                            ret++;
                            break;
                     }
                     ans=max(ans,ret);
              }
              printf("%d\n",ans);
       }
       return 0;
}

I题:没看,貌似没人做。

J题:给定三个字符串,问有多少种方法使等式成立。

暴力枚举:dfs爆搜

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<map>
using namespace std;
int used[20],vis[20];
char s1[30],s2[30],s3[30];
int ans,s[20];
int change(char str[])
{
       int len=strlen(str);
       if(len>1&&s[str[0]-'A']==0)return -1;
       int ans=0;
       for(int i=0;i<len;i++)
              ans=10*ans+s[str[i]-'A'];
       return ans;
}
void dfs(int step)
{
       if(step==5)
       {
              int a=change(s1);
              int b=change(s2);
              int c=change(s3);
              if(a==-1||b==-1||c==-1)return;
              if(a+b==c)ans++;
              if(a-b==c)ans++;
              if(a*b==c)ans++;
              if(b&&a==b*c)ans++;
              return;
       }
       if(!vis[step])
       {
              dfs(step+1);
              return;
       }
       for(int i=0;i<=9;i++)
       if(used[i]==0)
       {
              used[i]=1;
              s[step]=i;
              dfs(step+1);
              used[i]=0;
       }
}
int main()
{
       int i,j,k,m,n,T;
       scanf("%d",&T);
       while(T--)
       {
              scanf("%s%s%s",s1,s2,s3);
              memset(vis,0,sizeof(vis));
              for(i=0;i<strlen(s1);i++)vis[s1[i]-'A']=1;
              for(i=0;i<strlen(s2);i++)vis[s2[i]-'A']=1;
              for(i=0;i<strlen(s3);i++)vis[s3[i]-'A']=1;
              memset(used,0,sizeof(used));
              ans=0;
              dfs(0);
              printf("%d\n",ans);
       }
       return 0;
}

 

 

posted @ 2013-10-07 01:23  线性无关  阅读(122)  评论(0)    收藏  举报