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; }

浙公网安备 33010602011771号