3.16
https://vjudge.net/contest/154390#problem
A题
题意:给你27个字符分别有I L E三种组成,问你是否能组组成3*3*3的一整块?
思路:可以发现当字符为 I 和 L时它的下一个块的位置固定,当字符是 L 时他有四个方向,所以利用深搜去搜索出是否可能组成。
1 #include <iostream> 2 #include <bits/stdc++.h> 3 using namespace std; 4 int flag[3][3][3]; 5 char s[30]; 6 int ans; 7 int b[6][3]= {{1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1}}; 8 void dfs(int i,int j,int k,int p,int tmp) 9 { 10 int x,y,z; 11 if(tmp==26) 12 { 13 if(!flag[i][j][k]) 14 { 15 ans=1; 16 return ; 17 } 18 else 19 { 20 return ; 21 } 22 } 23 if(s[tmp]=='I') 24 { 25 x=i+b[p][0],y=j+b[p][1],z=k+b[p][2]; 26 if(x>=0&&x<=2&&y>=0&&y<=2&&z>=0&&z<=2&&!flag[i][j][k]) 27 { 28 flag[i][j][k]=1; 29 dfs(x,y,z,p,tmp+1); 30 flag[i][j][k]=0; 31 } 32 } 33 else if(s[tmp]=='L') 34 { 35 for(int t=0; t<6; t++) 36 { 37 if(t%3==p%3) 38 continue; 39 x=i+b[t][0],y=j+b[t][1],z=k+b[t][2]; 40 if(x>=0&&x<=2&&y>=0&&y<=2&&z>=0&&z<=2&&!flag[i][j][k]) 41 { 42 flag[i][j][k]=1; 43 dfs(x,y,z,t,tmp+1); 44 flag[i][j][k]=0; 45 } 46 if(ans) 47 break; 48 } 49 } 50 return ; 51 } 52 int main() 53 { 54 while(~scanf("%s",s)) 55 { 56 ans=0; 57 for(int i=0; i<3; i++) 58 { 59 for(int j=0; j<3; j++) 60 { 61 for(int k=0; k<3; k++) 62 { 63 int x=i+b[0][0],y=j+b[0][1],z=k+b[0][2]; 64 memset(flag,0,sizeof(flag)); 65 if(x>=0&&x<=2&&y>=0&&y<=2&&z>=0&&z<=2&&!flag[i][j][k]) 66 { 67 flag[i][j][k]=1; 68 dfs(x,y,z,0,1); 69 flag[i][j][k]=0; 70 } 71 if(ans) 72 break; 73 } 74 if(ans) 75 break; 76 } 77 if(ans) 78 break; 79 } 80 if(ans) 81 printf("YES\n"); 82 else 83 printf("NO\n"); 84 } 85 return 0; 86 }
B题
题意:给出两个有相同数量的叶子节点的树,问你最少需要多少种颜色进行染色。
思路:通过画图能知道最少的颜色只有2和3两种可能,其中若对A树从一个非叶子节点开始到所有叶子节点所走距离是奇数和偶数的数量和B树相同的话最少颜色一定是2,如果A的奇数数量等于B树的偶数数量那么结果还是2,否则是3。
1 #include <iostream> 2 #include <queue> 3 #include <vector> 4 #include <bits/stdc++.h> 5 using namespace std; 6 const int maxn=100005; 7 vector<int>mp[maxn]; 8 queue<int>que1,que2; 9 int flag[maxn],ans1[maxn],ans2[maxn]; 10 void dfs(int x,int step) 11 { 12 int tmp=0; 13 for(int i=0; i<mp[x].size(); i++) 14 { 15 if(!flag[mp[x][i]]) 16 { 17 tmp=1; 18 flag[mp[x][i]]=1; 19 dfs(mp[x][i],step+1); 20 } 21 } 22 if(tmp==0) 23 { 24 if(step%2==1) 25 que1.push(x); 26 else 27 que2.push(x); 28 } 29 return ; 30 } 31 int main() 32 { 33 int u,v,n,m; 34 while(~scanf("%d",&n)) 35 { 36 for(int i=0; i<maxn; i++) 37 mp[i].clear(); 38 for(int i=0; i<n-1; i++) 39 { 40 scanf("%d%d",&u,&v); 41 mp[u].push_back(v); 42 mp[v].push_back(u); 43 } 44 memset(flag,0,sizeof(flag)); 45 while(!que1.empty()) 46 que1.pop(); 47 while(!que2.empty()) 48 que2.pop(); 49 for(int i=1; i<=n; i++) 50 if(mp[i].size()>1) 51 { 52 flag[i]=1; 53 dfs(i,1); 54 break; 55 } 56 int k1=0,k2=0; 57 while(!que1.empty()) 58 { 59 ans1[k1++]=que1.front(); 60 que1.pop(); 61 } 62 while(!que2.empty()) 63 { 64 ans2[k2++]=que2.front(); 65 que2.pop(); 66 } 67 scanf("%d",&m); 68 for(int i=0; i<maxn; i++) 69 mp[i].clear(); 70 for(int i=0; i<m-1; i++) 71 { 72 scanf("%d%d",&u,&v); 73 mp[u].push_back(v); 74 mp[v].push_back(u); 75 } 76 memset(flag,0,sizeof(flag)); 77 for(int i=1; i<=m; i++) 78 if(mp[i].size()>1) 79 { 80 flag[i]=1; 81 dfs(i,1); 82 break; 83 } 84 if(que1.size()==k1||que2.size()==k1) 85 { 86 printf("2\n"); 87 int t=0; 88 if(k1==que1.size()) 89 { 90 while(!que1.empty()) 91 { 92 printf("%d %d\n",ans1[t++],que1.front()); 93 que1.pop(); 94 } 95 t=0; 96 while(!que2.empty()) 97 { 98 printf("%d %d\n",ans2[t++],que2.front()); 99 que2.pop(); 100 } 101 } 102 else 103 { 104 while(!que2.empty()) 105 { 106 printf("%d %d\n",ans1[t++],que2.front()); 107 que2.pop(); 108 } 109 t=0; 110 while(!que1.empty()) 111 { 112 printf("%d %d\n",ans2[t++],que1.front()); 113 que1.pop(); 114 } 115 } 116 } 117 else 118 { 119 printf("3\n"); 120 for(int i=0; i<k2; i++) 121 ans1[i+k1]=ans2[i]; 122 int t=0; 123 while(!que1.empty()) 124 { 125 ans2[t++]=que1.front(); 126 que1.pop(); 127 } 128 while(!que2.empty()) 129 { 130 ans2[t++]=que2.front(); 131 que2.pop(); 132 } 133 for(int i=0; i<t; i++) 134 printf("%d %d\n",ans1[i],ans2[i]); 135 } 136 137 } 138 return 0; 139 }
C题
D题
题意:有n台坏电脑,A修好一台要a分钟,B要b分钟,问两人一起修好n台的最短时间。
思路:使用二分将n分成A要修的台数和剩下B要修的台数,求两者的最大值的最小值。
1 #include <iostream> 2 #include<cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <bits/stdc++.h> 7 using namespace std; 8 int main() 9 { 10 long long n,x,y; 11 while(~scanf("%I64d%I64d%I64d",&n,&x,&y)) 12 { 13 long long l=0,r=n; 14 if(x>y) 15 swap(x,y); 16 long long ans=n*y,len=n*y; 17 long long mid; 18 while(l<=r) 19 { 20 mid=(l+r)/2; 21 if(mid*x<(n-mid)*y) 22 { 23 l=mid+1; 24 } 25 else if ((n-mid)*y<mid*x) 26 { 27 r=mid-1; 28 } 29 if(len>max((n-mid)*y,mid*x)) 30 { 31 len=max((n-mid)*y,mid*x); 32 } 33 if((n-mid)*y==x*mid) 34 { 35 len=x*mid; 36 break; 37 } 38 } 39 printf("%I64d\n",len); 40 } 41 return 0; 42 }
E题
题意:给你两个三角形的六个顶点,问组成的新图形有几个顶点?
思路:两个三角形有1 2 3个顶点重合,新图形有6 4 3个顶点
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 int main() 8 { 9 int a,b,c,d,e,f; 10 while(cin>>a>>b>>c>>d>>e>>f) 11 { 12 int t=0; 13 if(a==d) t++; 14 if(a==e) t++; 15 if(a==f) t++; 16 if(b==d) t++; 17 if(b==e) t++; 18 if(b==f) t++; 19 if(c==d) t++; 20 if(c==e) t++; 21 if(c==f) t++; 22 if(t==0||t==1) cout<<6<<endl; 23 else if(t==2) cout<<4<<endl; 24 else cout<<3<<endl; 25 } 26 return 0; 27 }
F题
G题
题意:一群人做同一个题,给你做之前的分数和这道题的分值,问排名存在变化的可能性。
思路:没想明白呢
1 #include <iostream> 2 #include <bits/stdc++.h> 3 using namespace std; 4 const int maxn=100005; 5 int a[maxn]; 6 double cnt[maxn],sum[maxn]; 7 int cmp(const int &a,const int &b) 8 { 9 return a>b; 10 } 11 int main() 12 { 13 int n,m; 14 // int c[12]={12,15,17,19,20,22,23,26,29,35,40,51}; 15 // for(int i=0;i<12;i++) 16 // b[i]=c[11-i]; 17 // int k=upper_bound(b,b+10,20,cmp)-b; 18 // printf("%d\n",k); 19 while(~scanf("%d%d",&n,&m)) 20 { 21 for(int i=0;i<n;i++) 22 { 23 scanf("%d",&a[i]); 24 } 25 for(int i=0;i<n;i++) 26 { 27 scanf("%lf",&cnt[i]); 28 if(i==0) 29 sum[i+1]=cnt[i]; 30 else 31 { 32 sum[i+1]=sum[i]+cnt[i]; 33 } 34 } 35 double ans=0.0; 36 for(int i=0;i<n;i++) 37 { 38 int l=upper_bound(a,a+i+1,a[i]+m,cmp)-a; 39 int r=lower_bound(a,a+i+1,a[i],cmp)-a; 40 //printf("%d %d\n",l,r); 41 ans+=(sum[r]-sum[l])*(1.0-cnt[i]); 42 } 43 printf("%.9lf\n",ans); 44 45 } 46 return 0; 47 }
H题
题意:给你一系列数让你进行n-1次相邻的两个数合并,再把每次合并之后的数进行相加,求最小的总和。
思路:经过几次计算就会发现当总和最小时,n加了(n-1)次,(n-1)加了(n-2)次,依次类推,就能求出最后的和。
1 #include <iostream> 2 #include <algorithm> 3 #include <bits/stdc++.h> 4 using namespace std; 5 typedef long long ll; 6 ll a[100005]; 7 int main() 8 { 9 ll n; 10 while(cin>>n) 11 { 12 scanf("%I64d",&a[0]); 13 for(int i=1;i<n;i++) 14 { 15 scanf("%I64d",&a[i]); 16 17 } 18 sort(a,a+n); 19 ll sum=0; 20 for(int i=0;i<n;i++) 21 sum+=a[i]*i; 22 printf("%I64d\n",sum); 23 24 25 26 } 27 return 0; 28 }
I题