2014西安全国邀请赛

陪人训练,只A了四个题,赛后五分钟AC J,难受

写题解的时候有点困,语言组织有点问题,有时间再更新 sorry

A - Wow! Such Doge!

题意:就给你一堆字符串,然后问你“doge"有多少个,不区分大小写

分析:随便咋么写都能AC。。

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int main(){
 6     ios_base::sync_with_stdio(0);
 7     cin.tie(0);
 8     char s;
 9     int result;
10     result=0;
11     int q=0;
12     while(cin>>s){
13         if(q==0){
14             if(s=='D'||s=='d'){
15                 q++;
16             }
17             else q=0;
18         }
19         else if(q==1){
20             if(s=='O'||s=='o'){
21                 q++;
22             }
23             else q=0;
24         }
25         else if(q==2){
26             if(s=='G'||s=='g'){
27                 q++;
28             }
29             else q=0;
30         }
31         else if(q==3){
32             if(s=='E'||s=='e'){
33                 q++;
34                 result++;
35                 q=0;
36             }
37             else q=0;
38         }
39     }
40     cout<<result<<endl;
41 
42 return 0;
43 }
View Code

B - Wow! Such Conquering!

 题意:有n个星球,现在要从1号星球出发,游历其他所有的星球,不需要返回1,求到其他所有星球的路程和最小是多少,每个星球还有一个deadline,表示游历那个星球的最晚时间。

 星球之间的路径长度已经给出。3<=n<=30

分析:直接跑一遍Floyd,求出任意两个星球之间的最短路,然后dfs搜索。不过这个需要剪枝,看到时限8秒,于是想当然,T了三发。基本上(1)判断到达当前点之后,如果以后有到达其他星球的时间大于他的deadline,那么久return (2)计算到达某点之后,要通过剩下的所有点的最少花费时间,大于result就return。注意这两个剪枝就好了。

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int d[105];
 6 int dj[105][105];
 7 int result,number=0;
 8 int n;
 9 bool vis[105];
10 void dfs(int x,int mx,int re,int number){
11     if(re+mx*(n-number)>result) return;
12     if(number==n){
13         result=min(result,re);
14         return;
15     }
16     for(int i=2;i<=n;i++){
17        if(vis[i]==false&&mx+dj[x][i]>d[i]) {
18          return ;
19        }
20     }
21     for(int i=2;i<=n;i++){
22         if(vis[i]==false&&mx+dj[x][i]<=d[i]){
23             vis[i]=true;
24             dfs(i,mx+dj[x][i],re+mx+dj[x][i],number+1);
25             vis[i]=false;
26         }
27     }
28 }
29 int main(){
30     ios_base::sync_with_stdio(0);
31     cin.tie(0);
32     memset(d,0,sizeof(d));
33     while(cin>>n){
34         memset(vis,false,sizeof(vis));
35         memset(dj,0x3f3f3f3f,sizeof(dj));
36         result=1e9+7;
37         for(int i=1;i<=n;i++){
38             for(int j=1;j<=n;j++){
39                 cin>>dj[i][j];
40             }
41         }
42         for(int k=1;k<=n;k++){
43             for(int i=1;i<=n;i++){
44                 for(int j=1;j<=n;j++){
45                     dj[i][j]=min(dj[i][j],dj[i][k]+dj[k][j]);
46                 }
47             }
48         }
49         for(int i=2;i<=n;i++){
50             cin>>d[i];
51         }
52         vis[1]=true;
53         dfs(1,0,0,1);
54         if(result==1e9+7) cout<<-1<<endl;
55         else cout<<result<<endl;
56     }
57 
58 return 0;
59 }
View Code

C - Wow! Such City!

 题意:有n个城市(n<=1000)然后输入m(<=1e6),然后输入 X 0, X 1, Y 0, Y 1,然后给你公式,让你计算Zk,然后这n个城市之间的路径又给你一个公式可以求出,最后让你求从0号城市到其他所有城市的最短路 mod m的最小值

分析:直接照着公式计算出任意两个城市之间的路径,然后跑最短路,然后%m取最小就可以了

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 long long x[1000005],y[1000005],z[1000005];
 6 long long mod1=5837501;
 7 long long mod2=9860381;
 8 long long mod3=8475871;
 9 long long mp[1005][1005];
10 long long dj[1005];
11 bool vis[10005];
12 long long n,m;
13 void djs(int x)
14 {
15     int u;
16     long long mi;
17     for(int i=1;i<n;i++){
18         dj[i]=mp[x][i];
19     }
20     vis[x]=true;
21     for(int i=1; i<n; i++){
22         mi=1e18;
23         u = -1;
24         for (int j=1; j<n; j++){
25             if (!vis[j]&&dj[j]<mi){
26                 u=j;
27                 mi=dj[j];
28             }
29         }
30         if(u==-1) break;
31         vis[u]=true;
32         for (int j=1;j<n;j++){
33             if(!vis[j]){
34                 if(dj[u]+mp[u][j]<dj[j]){
35                     dj[j]=dj[u]+mp[u][j];
36                 }
37             }
38         }
39     }
40 }
41 int main(){
42     ios_base::sync_with_stdio(0);
43     cin.tie(0);
44     while(cin>>n>>m>>x[0]>>x[1]>>y[0]>>y[1]){
45         for(int i=0;i<n;i++){
46             dj[i]=1e18;
47         }
48         memset(vis,false,sizeof(vis));
49         for(int i=0;i<2;i++){
50             z[i]=(x[i]*90123+y[i])%mod3+1;
51         }
52         for(int i=2;i<=n*n;i++){
53             x[i]=(12345+x[i-1]*23456+x[i-2]*34567+x[i-1]*x[i-2]*45678)%mod1;
54             y[i]=(56789+y[i-1]* 67890+y[i-2]*78901+y[i-1]*y[i-2]*89012)%mod2;
55             z[i]=(x[i]*90123+y[i])%mod3+1;
56         }
57         for(int i=0;i<n;i++){
58             for(int j=0;j<n;j++){
59                 if(i==j){
60                     mp[i][j]=0;
61                 }
62                 else mp[i][j]=z[i*n+j];
63             }
64         }
65         djs(0);
66         long long result=m-1;
67         for(int i=1;i<n;i++){
68            // cout<<dj[i]<<endl;
69             result=min(result,dj[i]%m);
70         }
71         cout<<result<<endl;
72     }
73 
74 return 0;
75 }
View Code

D - Wow! Such String!

题意:给你一个n(n<=5000000),然后让你构造一个只包含小写字母的字符串,使得每一个长度大于等于4的子串在构造串中最多出现1次。

分析:由于限制长度大于等于4的子串只出现1次,我们想到长度为4的子串共有26*26*26*26种情况,可以直接枚举,对于每位我们枚举a到z的某一个,然后每次枚举后面的时候,我们需要判断这个序列在之前的串中是否出现过。当然这样枚举再碰到z之后会继续枚举aaa,这个时候就会无法枚举后一个,因此我们在没法继续枚举后一个的时候,加一个回溯,这样就能继续向下枚举了,最后只需要在最后把a加上就行。当n大于26*26*26*26+3时,输出 Impossible。学弟用枚举26进制的方法也过了,在枚举26进制,连接数字的时候需要注意一下,其他没什么情况。

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 long long a[500005];
 6 bool mp[27][27][27][27];
 7 int main(){
 8     ios_base::sync_with_stdio(0);
 9     cin.tie(0);
10     int n;
11     for(int i=1;i<=4;i++){
12         a[i]=0;
13     }
14     memset(mp,false,sizeof(mp));
15     memset(a,0,sizeof(a));
16     mp[a[1]][a[2]][a[3]][a[4]]=true;
17     int d=26*26*26*26;
18     int p=0;
19     for(int i=5;i<=d;i++){
20         p=0;
21         for(int j=0;j<26;j++){
22             a[i]=j;
23             if(!mp[a[i-3]][a[i-2]][a[i-1]][a[i]]){
24                 mp[a[i-3]][a[i-2]][a[i-1]][a[i]]=true;
25                 p=1;
26                 break;
27             }
28         }
29         if(p==0){
30             i=i-2;
31         }
32     }
33     while(cin>>n){
34         if(n>d+3) {cout<<"Impossible"<<endl;continue;}
35         for(int i=1;i<=n;i++){
36             char c=('a'+a[i]);
37             cout<<c;
38         }
39         cout<<endl;
40     }
41 
42 return 0;
43 }
View Code

J - Tunnels

 题意:给你n,m分别代表正方形地图的边长和管道的个数,在这个地图中有m个管道,分别有入口和出口。从入口到出口不需要花费时间,然后问你从任意管道进入,遍历完其他管道,且每个管道只经过一次,求所需要的最短路是多少。n,m<=15

分析:由于题目限制每个管道只经过一次,然后看一下数据范围,可以确定是状态压缩。首先我们需要bfs预处理每个管道之间的距离,接下来我们就可以利用状压DP来解决了。

  对于某一个状态dp[i][j]表示经过的管道为i的二进制位为1的管道,最后一个经过的管道是j管道。现在我们要转移到下一个状态。从i状态可以到达的状态是把i的二进制为0 的某一位变为1的状态。比如从dp[i][j]状态要求再经过第k个管道,那么最终状态就会变成dp[i|(1<<(k-1))],那么我们的状态转移方程就是dp[i|(1<<(k-1))][k]=min(dp[i|(1<<(k-1))][k],dp[i][j]+mp[j][k]) 我的管道编号是从1开始的。然后进行状态转移时我们必须保证i的第j位为1,且第k位为0,且状态i是存在的,这样就可以了。(我这个bfs写的是真jb恐怖,这样写不好,大家别学我,还是把方向存在数组里比较稳 23333)

AC代码:、

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 char c[20][20];
  6 struct st{
  7     int a,b,c,d;
  8 }s[25];
  9 int dj[25][25];
 10 int mp[25][25];
 11 bool vis[25][25];
 12 int n,m;
 13 int result;
 14 int dp[32768+5][25];
 15 struct qt{
 16     int x,y;
 17     qt(int _x,int _y){
 18         x=_x;
 19         y=_y;
 20     }
 21 };
 22 void bfs(int x1,int y1){
 23     queue<qt>q;
 24     q.push(qt(x1,y1));
 25     while(!q.empty()){
 26         qt p=q.front();
 27         q.pop();
 28         if((!vis[p.x+1][p.y])&&c[p.x+1][p.y]=='.'){
 29             dj[p.x+1][p.y]=dj[p.x][p.y]+1;
 30             vis[p.x+1][p.y]=true;
 31             q.push(qt(p.x+1,p.y));
 32         }
 33         if((!vis[p.x-1][p.y])&&c[p.x-1][p.y]=='.'){
 34             dj[p.x-1][p.y]=dj[p.x][p.y]+1;
 35             vis[p.x-1][p.y]=true;
 36             q.push(qt(p.x-1,p.y));
 37         }
 38         if((!vis[p.x][p.y+1])&&c[p.x][p.y+1]=='.'){
 39             dj[p.x][p.y+1]=dj[p.x][p.y]+1;
 40             vis[p.x][p.y+1]=true;
 41             q.push(qt(p.x,p.y+1));
 42         }
 43         if((!vis[p.x][p.y-1])&&c[p.x][p.y-1]=='.'){
 44             dj[p.x][p.y-1]=dj[p.x][p.y]+1;
 45             vis[p.x][p.y-1]=true;
 46             q.push(qt(p.x,p.y-1));
 47         }
 48     }
 49 }
 50 int main(){
 51     ios_base::sync_with_stdio(0);
 52     cin.tie(0);
 53     while(cin>>n>>m){
 54         memset(c,'#',sizeof(c));
 55         for(int i=1;i<=n;i++){
 56             for(int j=1;j<=n;j++){
 57                 cin>>c[i][j];
 58             }
 59         }
 60         memset(mp,0x3f3f3f3f,sizeof(mp));
 61         for(int i=1;i<=m;i++){
 62             cin>>s[i].a>>s[i].b>>s[i].c>>s[i].d;
 63         }
 64         for(int i=1;i<=m;i++){
 65             memset(dj,0x3f3f3f3f,sizeof(dj));
 66             dj[s[i].c][s[i].d]=0;
 67             memset(vis,false,sizeof(vis));
 68             vis[s[i].c][s[i].d]=true;
 69             bfs(s[i].c,s[i].d);
 70             for(int j=1;j<=m;j++){
 71                 if(i!=j){
 72                     mp[i][j]=dj[s[j].a][s[j].b];
 73                 }
 74             }
 75         }
 76         int d=1;
 77         memset(dp,0x3f3f3f3f,sizeof(dp));
 78         for(int i=1;i<=m;i++){
 79             dp[d][i]=0;
 80             d*=2;
 81         }
 82         for(int i=1;i<d;i++){
 83             for(int j=1;j<=m;j++){
 84                 if(!i&(1<<(j-1))) continue;
 85                 for(int k=1;k<=m;k++){
 86                     if(i&(1<<(k-1))||mp[j][k]==0x3f3f3f3f) continue;
 87                     if(dp[i][j]==0x3f3f3f3f) continue;
 88                     dp[i|(1<<(k-1))][k]=min(dp[i|(1<<(k-1))][k],dp[i][j]+mp[j][k]);
 89                 }
 90             }
 91         }
 92         result=0x3f3f3f3f;
 93         for(int i=1;i<=m;i++){
 94             result=min(dp[d-1][i],result);
 95         }
 96         if(result==0x3f3f3f3f){
 97             cout<<-1<<endl;
 98         }
 99         else cout<<result<<endl;
100     }
101 return 0;
102 }
View Code

然后就一共过了5个题 其他题一个人也没时间读了,英语比较菜,加油加油

原文地址:https://www.cnblogs.com/ls961006/p/8688729.html