A http://acm.hust.edu.cn/vjudge/contest/view.action?cid=98960#problem/A
题意:给一个正方形,四边上有A-Z带+-,如果是00就不能连任何的。如果两个正方形的边字母相同,正负号相反,就可以连起来。问给输入的n种,每种无限个,可否构成无限大的平面。给的正方形可以旋转或者对称的翻转。
解法:想要无限大,就想能否有几个正方形够成环了,构成环就可以无限延伸。如何判环可以拓扑排序,或者tarjan缩点。关键在建图。对于每个正方形,其中一条边的假设是A+,那么A-就可以通像这个正方形的另外3个符号。建一条有向边。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=4e4+10; 23 char a[M][16]; 24 char str[2][16]= {"bounded","unbounded"}; 25 int n; 26 vector<int> id; 27 class Toposort { ///拓扑排序(矩阵) O(V^2) 28 static const int MV=1e2+10;///点的个数 29 bool mat[MV][MV]; 30 int n,ret[MV],d[MV],i,j,k; 31 public: 32 void init(int tn) { ///传入点数,点下标0 开始 33 n=tn; 34 for(i=0; i<n; i++) 35 for(j=0; j<n; j++) 36 mat[i][j]=false; 37 } 38 void add(int u,int v) { 39 mat[u][v]=true; 40 } 41 bool solve() { ///无法完成排序,返回flase 42 for(i=0; i<n; i++) { 43 d[i]=0; 44 for(j=0; j<n; j++) { 45 d[i]+=mat[j][i]; 46 } 47 } 48 for(k=0; k<n; k++) { 49 for(i=0; i<n; i++) { 50 if(!d[i]) break; 51 } 52 if(i==n) return false; 53 d[i]=-1; 54 for(j=0; j<n; j++) { 55 d[j]-=mat[i][j]; 56 } 57 ret[k]=i; 58 } 59 return true; 60 } 61 int getvalue(int id) { ///0~n-1 中存着字典序最小的序列 62 return ret[id]; 63 } 64 } gx; 65 int get_id(char a,char b){ 66 int result=a-'A'; 67 if(b=='-') result+=26; 68 return result; 69 } 70 int get_other(int a){ 71 if(a<26) return a+26; return a-26; 72 } 73 int solve() { 74 gx.init(52); 75 for(int i=0; i<n; i++) { 76 id.clear(); 77 for(int j=0;j<8;j+=2){ 78 if(a[i][j]=='0') continue; 79 id.push_back(get_id(a[i][j],a[i][j+1])); 80 } 81 int len=id.size(); 82 for(int j=0;j<len;j++){ 83 for(int k=j+1;k<len;k++){ 84 gx.add(get_other(id[j]),id[k]); 85 gx.add(get_other(id[k]),id[j]); 86 } 87 } 88 } 89 return !gx.solve(); 90 } 91 int main() { 92 #ifdef txtout 93 freopen("in.txt","r",stdin); 94 freopen("out.txt","w",stdout); 95 #endif 96 while(~scanf("%d",&n)) { 97 for(int i=0; i<n; i++) { 98 scanf("%s",a[i]); 99 } 100 puts(str[solve()]); 101 } 102 return 0; 103 }
发现缩点模板没法判自环。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=4e4+10; 23 char a[M][16]; 24 char str[2][16]= {"bounded","unbounded"}; 25 int n; 26 vector<int> id; 27 bool mat[64][64]; 28 class Tarjan { ///有向图强连通分量缩点O(V+E) 29 static const int ME=1e4+10; ///边的个数 30 static const int MV=1e2+10; ///点的个数 31 int n,Index,Bcnt,num[MV],belong[MV],dfn[MV],low[MV]; 32 bool instack[MV]; 33 stack<int> s; 34 void tarjan(int u) { 35 dfn[u]=low[u]=++Index; 36 instack[u]=true; 37 s.push(u); 38 int v; 39 for(int i=g.head[u]; ~i; i=g.e[i].next) { 40 v=g.e[i].v; 41 if(!dfn[v]) { 42 tarjan(v); 43 low[u]=min(low[u],low[v]); 44 continue; 45 } 46 if(instack[v]) { 47 low[u]=min(low[u],dfn[v]); 48 } 49 } 50 if(dfn[u]!=low[u]) return ; 51 Bcnt++; 52 do { 53 v=s.top(); 54 s.pop(); 55 instack[v]=false; 56 belong[v]=Bcnt; 57 num[Bcnt]++; 58 } while(u!=v); 59 } 60 struct G { 61 struct E { 62 int v,next; 63 } e[ME]; 64 int le,head[MV]; 65 void init(int n) { 66 le=0; 67 for(int i=0; i<=n; i++) head[i]=-1; 68 } 69 void add(int u,int v) { 70 e[le].v=v; 71 e[le].next=head[u]; 72 head[u]=le++; 73 } 74 } g; 75 public: 76 void init(int tn) { ///传入点数,点下标1 开始 77 n=tn; 78 g.init(n); 79 } 80 void add(int u,int v) { 81 g.add(u,v); 82 } 83 void solve() { 84 Index=Bcnt=0; 85 for(int i=1; i<=n; i++) { 86 num[i]=dfn[i]=low[i]=instack[i]=0; 87 } 88 while(!s.empty()) s.pop(); 89 for(int i=1; i<=n; i++) { 90 if(!dfn[i]) { 91 tarjan(i); 92 } 93 } 94 } 95 int getbcnt() { ///强连通分量的个数 96 return Bcnt; 97 } 98 int getbelong(int id) { ///属于哪个分量,分量下标1 开始 99 return belong[id]; 100 } 101 int getnum(int id) { ///某个分量的点的个数 102 return num[id]; 103 } 104 } gx; 105 int get_id(char a,char b) { 106 int result=a-'A'; 107 if(b=='-') result+=26; 108 return result; 109 } 110 int get_other(int a) { 111 if(a<26) return a+26; 112 return a-26; 113 } 114 int solve() { 115 mt(mat,0); 116 for(int i=0; i<n; i++) { 117 id.clear(); 118 for(int j=0; j<8; j+=2) { 119 if(a[i][j]=='0') continue; 120 id.push_back(get_id(a[i][j],a[i][j+1])); 121 } 122 int len=id.size(); 123 for(int j=0; j<len; j++) { 124 for(int k=j+1; k<len; k++) { 125 mat[get_other(id[j])][id[k]]=true; 126 mat[get_other(id[k])][id[j]]=true; 127 } 128 } 129 } 130 gx.init(52); 131 for(int i=0;i<52;i++){ 132 for(int j=0;j<52;j++){ 133 if(!mat[i][j]) continue; 134 if(i==j) return 1; 135 gx.add(i+1,j+1); 136 } 137 } 138 gx.solve(); 139 return gx.getbcnt()!=52; 140 } 141 int main() { 142 #ifdef txtout 143 freopen("in.txt","r",stdin); 144 freopen("out.txt","w",stdout); 145 #endif 146 while(~scanf("%d",&n)) { 147 for(int i=0; i<n; i++) { 148 scanf("%s",a[i]); 149 } 150 puts(str[solve()]); 151 } 152 return 0; 153 }
F http://acm.hust.edu.cn/vjudge/contest/view.action?cid=98960#problem/F
题意:有n台机器,每个机器由两个部分组成,每个部分需要k个电池,输入n,k,和2*n*k个电池的值。求如何分配电池,使得每个机器的差值d中最大的最小。差值d等于机器两部分电池的最小值之差。
解法:先把电池按照值小到大排序,二分答案d,判断是否可以满足,如果可以满足,则找更小的,如果不可以则找更大的,就能找到最小的d。判断满足即判断所有的机器差值都小于等于二分的差值即可。从小到大选择,如果相邻的两个差值满足,则直接将这两个座位一个机器的两部分,如果不满足,就将小的扔到之前已经满足的部分的后面。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e6+10; 23 int a[M]; 24 int n,k,m; 25 bool judge(int mid){ 26 int save=0,sum=0; 27 for(int i=0;i+1<m;i++){ 28 if(a[i+1]-a[i]>mid){ 29 if(save==0) return false; 30 save--; 31 } 32 else{ 33 save+=2*k-2; 34 sum++; 35 if(sum==n) return true; 36 i++; 37 } 38 } 39 return false; 40 } 41 int solve(){ 42 sort(a,a+m); 43 int L=0,R=a[m-1]-a[0],result=R; 44 while(L<=R){ 45 int mid=(L+R)>>1; 46 if(judge(mid)){ 47 result=mid; 48 R=mid-1; 49 } 50 else{ 51 L=mid+1; 52 } 53 } 54 return result; 55 } 56 int main(){ 57 #ifdef txtout 58 freopen("in.txt","r",stdin); 59 freopen("out.txt","w",stdout); 60 #endif 61 while(~scanf("%d%d",&n,&k)){ 62 m=2*n*k; 63 for(int i=0;i<m;i++){ 64 scanf("%d",&a[i]); 65 } 66 printf("%d ",solve()); 67 } 68 return 0; 69 }
J http://acm.hust.edu.cn/vjudge/contest/view.action?cid=98960#problem/J
题意:圆与多边形的交
解法:不会,模板
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e2+10; 23 struct point { 24 double x,y; 25 } p[M]; 26 double r; 27 int n; 28 class Area_of_circle_polygon { 29 double xmult(point p1,point p2,point p0) { ///计算向量叉积(P1-P0)x(P2-P0) 30 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); 31 } 32 double Square(double x) { ///平方 33 return x*x; 34 } 35 double Distance(point a,point b) { ///平面两点距离 36 return sqrt(Square(a.x-b.x)+Square(a.y-b.y)); 37 } 38 double dmult(point p1,point p2,point p0) { 39 return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y); 40 } 41 double help_cal(point a,point b,point c,double r,double C){ 42 double d=dmult(a,c,b); 43 double x=xmult(a,c,b); 44 return (d+sqrt(r*r*C*C-x*x))/C; 45 } 46 double help_again(double tS,double x,double C,double r,double B){ 47 return asin(tS*(1-x/C)*2/r/B)*r*r*0.5+tS*x/C; 48 } 49 double cal_area(point a,point b,point c,double r) { 50 double A,B,C,x,y,tS; 51 A=Distance(b,c); 52 B=Distance(a,c); 53 C=Distance(b,a); 54 tS=xmult(a,b,c)*0.5; 55 if(A<r&&B<r) return tS; 56 if(A<r&&B>=r) { 57 x=help_cal(a,b,c,r,C); 58 return help_again(tS,x,C,r,B); 59 } 60 if(A>=r&&B<r) { 61 y=help_cal(b,a,c,r,C); 62 return help_again(tS,y,C,r,A); 63 } 64 if(fabs(xmult(a,b,c))>=r*C||dmult(b,c,a)<=0||dmult(a,c,b)<=0) { 65 double x=xmult(a,b,c); 66 double tmp=-asin(x/A/B); 67 if(dmult(a,b,c)<0){ 68 if(x<0){ 69 tmp-=pi; 70 } 71 else{ 72 tmp+=pi; 73 } 74 } 75 else{ 76 tmp=-tmp; 77 } 78 return tmp*r*r*0.5; 79 } 80 x=help_cal(a,b,c,r,C); 81 y=help_cal(b,a,c,r,C); 82 double t1=help_again(tS,x,C,r,B); 83 double t2=help_again(tS,y,C,r,A); 84 return t1+t2-tS; 85 } 86 public: 87 double solve(point p[],int n,point circle,double r) {///传入多边形点数组,点个数,圆心,半径 88 double area=0; 89 for(int i=0; i<n; i++) { 90 area+=cal_area(p[i], p[(i+1)%n], circle, r); 91 } 92 return area; 93 } 94 } gx; 95 96 int main() { 97 #ifdef txtout 98 freopen("in.txt","r",stdin); 99 freopen("out.txt","w",stdout); 100 #endif 101 point c; 102 c.x=c.y=0; 103 while(~scanf("%d%lf",&n,&r)) { 104 for(int i=0; i<n; i++) { 105 scanf("%lf%lf",&p[i].x,&p[i].y); 106 } 107 printf("%.9f ",gx.solve(p,n,c,r)); 108 } 109 return 0; 110 }
end