今天状态很差,各种卡手,仰望能够1A 各题的天命之子。
这套是16软工的期末考试题,题目难度无限接近程设难度。
谨记谢大的教诲,代码要美观,气气+1
A Rotate http://172.22.112.249/exam/index.php/problem/exam_read/id/1360/exam_id/161
思路:
听谢大的,瞎搞吧,转内圈比转外圈简单。
太裸了,也太恶心了,这题能写一个小时。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int pos[]={6,7,10,11};
int fx[]={6,6,7,10};
int fy[]={10,7,11,11};
int main(){
int a[55];
int t;cin>>t;
while(t--){
for(int i=1;i<=16;i++){
scanf("%d",a+i);
}
int ans=INT_MIN;
for(int i=0;i<4;i++){
ans = max( ans , a[1]+a[2]+a[5]+a[pos[i]]);
ans = max( ans , a[3]+a[4]+a[8]+a[pos[i]]);
ans = max( ans , a[9]+a[13]+a[14]+a[pos[i]]);
ans = max( ans , a[12]+a[15]+a[16]+a[pos[i]]);
ans = max( ans , a[2]+a[3]+a[fx[i]]+a[fy[i]]);
ans = max( ans , a[8]+a[12]+a[fx[i]]+a[fy[i]]);
ans = max( ans , a[14]+a[15]+a[fx[i]]+a[fy[i]]);
ans = max( ans , a[5]+a[9]+a[fx[i]]+a[fy[i]]);
}
cout<<max(ans , a[6]+a[7]+a[10]+a[11])<<endl;
}
return 0;
}
B Distance http://172.22.112.249/exam/index.php/problem/exam_read/id/1361/exam_id/161
思路:
暴力肯定超时,复杂度O(N*M)
谢大提供的解法应该复杂度O(NlogN + MlogM + N + M)
讲题的时候说了,在此不写了,这里有一个复杂度低一丢丢的做法:复杂度O((N+M)*log(N))
对于A序列,我们进行排序。
对于每一个b,用二分查找找到大于等于b的最小值,然后更新答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,a[100005],m,b;
int main(){
int t;cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
sort(a+1,a+1+n);
int ans=2e9+10;
for(int i=0;i<m;i++){
scanf("%d",&b);
int pos = lower_bound(a+1,a+1+n,b)-a;
if(pos>n)pos=n;
if(pos>1){
ans = min(ans,abs(b-a[pos-1]));
}
ans = min(ans , abs(b-a[pos]));
}cout<<ans<<endl;
}
return 0;
}
C Min Base http://172.22.112.249/exam/index.php/problem/exam_read/id/1362/exam_id/161
思路:
听谢大的,暴力来就行。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
bool check(ll a,int b){
int vis[65]={0};
while(a){
vis[a%b]++;
a/=b;
}
if(*max_element(vis,vis+b+1)<=1)return 1;
return 0;
}
int main(){
int t;cin>>t;
while(t--){
cin>>n;
for(int b=2;;b++){
if(check(n,b)){
printf("%d\n",b);break;
}
}
}
return 0;
}
D Substring http://172.22.112.249/exam/index.php/problem/exam_read/id/1363/exam_id/161
思路:
尝试了一下复杂度O(T*|S|log|S|*26)的做法,由于常数太大了,TLE,
想了一下应该可以把26个字符压缩一下,说不定能过。
谢大的做法应该是最优解,复杂度O(T*|S|*26)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int vis[256];
int main(){
char s[2005];
while(scanf("%s",s+1)!=EOF){
memset(vis,0,sizeof vis);
int cnt=0;
int len=strlen(s+1);
int ans=0x3f3f3f3f;
for(int i=1;i<=len;i++){
if(vis[s[i]]==0){
cnt++;
} vis[s[i]]=i;
if(cnt==26){
int dis=INT_MIN;
for(int j='a';j<='z';j++){
dis=max(dis , i-vis[j]+1);
}
ans = min( ans , dis);
}
}
if(cnt<26)ans=0;
cout<<ans<<endl;
}
return 0;
}
E Ball http://172.22.112.249/exam/index.php/problem/exam_read/id/1364/exam_id/161
思路:
floyd求一下多源最短路,或者用拓扑排序也能做。
由于给的n很小,floyd代码较简单,没必要写拓扑排序。
首先初始化dis矩阵,dis[i][j]表示从i到j的最短路。
然后建边,对于m次称重,我们把a比b重认为是a能到达b,b不能到达a,
所以建立有向边。
跑一边floyd,复杂度O(N*N*N)
然后对于每个点a,我们判断a能到达多少点,用cnt1计数;
同时计算一下有多少点能到达a,用cnt2计数,
如果cnt1+cnt2==n-1 && cnt1==cnt2
说明a点是中点,如果有多个中点,输出0。
提供一下拓扑排序的思路:
设定一个level数组,每次把入度为0的点压入队列,然后记录它的level,处理完毕之后,得到的level数组可以直接来判断中点是否存在以及个数。复杂度是要比floyd低的。(这样口头ac,下次谢大要改数据范围了,气气+1)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100;
const int inf = 100000;
int n,m,u,v;
int dis[maxn][maxn];
int main(){
int t;cin>>t;
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)dis[i][j]=0;
else dis[i][j]=inf;
}
}
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
dis[u][v]=1;
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dis[i][k]<inf && dis[k][j]<inf){
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
}
int id=0,ok=1;
for(int i=1;i<=n;++i){
int cnt1=0,cnt2=0;
for(int j=1;j<=n;j++){
if(i==j)continue;
if(dis[i][j]<inf){
cnt1++;
}
else{
if(dis[j][i]<inf){
cnt2++;
}
}
}
if(cnt1+cnt2==n-1){
if(cnt1==cnt2){
if(id)ok=0;
else id=i;
}
}
}
if(ok&&id)printf("%d\n",id);
else printf("0\n");
}
return 0;
}
F Black White Chess http://172.22.112.249/exam/index.php/problem/exam_read/id/1365/exam_id/161
思路:
这次我学乖了,我不乱写了。
跟上次模考题一样的,17种状态。
那么很简单的一个bfs,初始压入0和1<<16-1,它们的step是0。
然后跑个最裸的bfs就过了。
复杂度不好说,反正肯定是不会超时的。如果非要说,那由于状态只有1<<16种,bfs时不会超过这么多次,而每次询问都是O(1)的。
谢老师说了,代码要写的好看,不然不及格。
#include <bits/stdc++.h>
using namespace std;
int vis[1<<16+10];
int multi[]={
0x0000f000,0x00000f00,0x000000f0,0x0000000f,
0x00008888,0x00004444,0x00002222,0x00001111,
0x0000cc00,0x00006600,0x00003300,
0x00000cc0,0x00000660,0x00000330,
0x000000cc,0x00000066,0x00000033
};
void bfs(){
queue<int> q;
vis[0]=1;vis[(1<<16)-1]=1;
q.push(0);q.push((1<<16)-1);
while(!q.empty()){
int now = q.front();q.pop();
int val;
for(int i=0;i<17;i++){
val = now ^ multi[i];
if(vis[val])continue;
vis[val]=vis[now]+1;
q.push(val);
}
}
}
int main(){
bfs();
int k;scanf("%d",&k);
char s[100];
while(k--){
scanf("%s",s);
int val1=0;
for(int i=0;i<16;i++){
if(s[i]=='1')val1+=(1<<i);
}
printf("%d\n",vis[val1]-1);
}
return 0;
}
转载请注明出处~~