狗狗40題~ (Volume A)

A - The Willy Memorial Program

大模擬題……

一開始的思路不對,修修補補WA了十發。當時想直接一個並查集做連通來搞定它,結果發現不能很好地判斷各管的水位。究其原因還是因爲這個是跟進水的過程順序有關的。

所以最後Ac的思路還是按模擬來做,在已經連通的管子中找最低的link連出去,不斷更新水位,合併管子。

有些細節注意一下,AC~

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define INF 200000000
           
typedef long long ll;
int p,lk;     
struct pipe{
   int bot,top,lp;
}pp[30];
struct link{
   int u,v,h;
}ln[60];
int fa[30],vis[60],hs[30],visp[30];
int cmp(struct link a,struct link b){
   return a.h>b.h;
}
void init(){
   for(int i=1;i<=p;i++)fa[i]=i;
}
int finds(int x){
   return fa[x]!=x?fa[x]=finds(fa[x]):x;
}
void unions(int u,int v){
   int fu=finds(u),fv=finds(v);
   if(fu!=fv)fa[fu]=fv;
}
int main(){
//("a.in","r",stdin);freopen("a.out","w",stdout);
     int t;
     scanf("%d",&t);
     while(t--){
        memset(vis,0,sizeof vis);
        memset(visp,0,sizeof visp);
        scanf("%d",&p);
        int left,up,hi;
        for(int i=1;i<=p;i++){
            scanf("%d%d%d",&left,&up,&hi);
            pp[i].lp=left;pp[i].top=up;
            pp[i].bot=up+hi;
        }
        scanf("%d",&lk);
        for(int i=1;i<=lk;i++){
            scanf("%d%d%d",&left,&ln[i].h,&hi);
            for(int j=1;j<=p;j++)if(pp[j].bot>=ln[i].h&&pp[j].top<=ln[i].h){
               if(pp[j].lp+1==left)ln[i].u=j;
               if(pp[j].lp==left+hi)ln[i].v=j;
            }
        }
        sort(ln+1,ln+lk+1,cmp);
        int now=1,y=0,tar,h0,find=0,flag;
        scanf("%d%d",&tar,&h0);
        if(h0>pp[tar].bot||h0<=pp[tar].top){
            printf("No Solution\n");
            continue;
        }
        for(int i=1;i<=p;i++)hs[i]=pp[i].bot;
        while(!find){
           visp[now]=1;
           if(now==tar)find=1;
           if(find){
              flag=1;
              init();
              for(int i=1;i<=lk&&ln[i].h>=h0;i++)unions(ln[i].u,ln[i].v);
              for(int i=1;i<=p;i++)if(finds(i)==finds(tar)){
                   if(h0<=pp[i].top)flag=0;
                   hs[i]=min(hs[i],h0);
              }
           }else{
              flag=0;
              int pos;
              for(pos=1;pos<=lk;pos++)if(!vis[pos])
                if(visp[ln[pos].u]^visp[ln[pos].v]){flag=1;break;}
              if(!flag)break;
              now=visp[ln[pos].u]?ln[pos].u:ln[pos].v;
              y=ln[pos].h;
              vis[pos]=1;
              init();
              for(int i=1;i<=lk&&ln[i].h>y;i++)unions(ln[i].u,ln[i].v);
              for(int i=1;i<=p;i++)if(finds(i)==finds(now))hs[i]=min(hs[i],y);
              now=visp[ln[pos].v]?ln[pos].u:ln[pos].v;
           }
        }
        for(int i=1;i<=p;i++)if(hs[i]<pp[i].top){flag=0;break;}
        if(!flag){
           printf("No Solution\n");
           continue;
        }
        int ans=0;
        for(int i=1;i<=p;i++)ans+=pp[i].bot-hs[i];
        printf("%d\n",ans);
     }
     return 0;
}

C - Transmitters

暴力不多說……(必須有一個點在直徑上)

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
           
typedef long long ll;
int n,x0,y0,x[200],y[200];
double r;
int cal_above(double k){
   int i,cnt=0;
   for(i=0;i<n;i++)
     if((x[i]-x0)*(x[i]-x0)+(y[i]-y0)*(y[i]-y0)<=r*r && y[i]>=y0+k*(x[i]-x0))
       cnt++;
   return cnt;
}  
int cal_below(double k){
   int i,cnt=0;
   for(i=0;i<n;i++)
     if((x[i]-x0)*(x[i]-x0)+(y[i]-y0)*(y[i]-y0)<=r*r && y[i]<=y0+k*(x[i]-x0))
       cnt++;
   return cnt;
}       
int main(){//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
   while(scanf("%d%d%lf",&x0,&y0,&r) && r>0){
     int i,ans=0;
     scanf("%d",&n);
     for(i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]);
     double k;
     for(i=0;i<n;i++)if(x[i]!=x0){
       k=(double)(y[i]-y0)/(x[i]-x0);
       ans=max(ans,cal_above(k));
       ans=max(ans,cal_below(k));
     }
     int c1=0,c2=0;
     for(i=0;i<n;i++)if((x[i]-x0)*(x[i]-x0)+(y[i]-y0)*(y[i]-y0)<=r*r){
       if(x[i]<=x0)c1++;
       if(x[i]>=x0)c2++;
     }
     ans=max(ans,c1);ans=max(ans,c2);
     printf("%d\n",ans);
   }
   return 0;
}

H - Mondriaan's Dream

一個經典的狀壓dp,需要用dfs搜索填充方案,然後按下一行的狀態dp

<span style="font-size:18px;">#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
           
typedef long long ll;
int h,w;
ll dp[20][1<<13];
void dfs(int sta,int cur,int ori,int beg){
   dp[cur+1][sta]+=dp[cur][ori];
   int bas=3<<beg;
   for(int i=beg;i<=w-2;i++){
      if((sta&bas)==0)
            dfs(sta|bas,cur,ori,i+1);
      bas<<=1;
   }
}           
int main(){
   
   while(scanf("%d%d",&h,&w) && w){
     int i,j,FULL=(1<<w)-1;
     memset(dp,0,sizeof dp);
     dp[0][FULL]=1;
     for(i=0;i<h;i++)
       for(j=0;j<(1<<w);j++){
           dfs(FULL^j,i,j,0);
       }
     printf("%lld\n",dp[h][FULL]);
   }
   return 0;
}</span>

F - Space Station Shielding

因爲這題知道了有一個小算法叫做 FloodFill ,簡單來說就是bfs,從外面的點搜索所有可以reach的點,然後把周圍如果和格子接觸就染色。

這就相當於把所有在表面的面染色了。

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
           
typedef long long ll;
int vis[80][80][80],g[80][80][80];
int ans,n,m,k,l;
int dx[6]={1,-1,0,0,0,0},dy[6]={0,0,1,-1,0,0},dz[6]={0,0,0,0,1,-1};
void bfs(int now){
   int q[80*80*80],from=0,to=0;
   q[to++]=now;
   int vx,vy,vz,d,ux,uy,uz;
   while(from<to){
       vx=q[from]%n;
       vy=(q[from]%(m*n))/n;
       vz=q[from]/(m*n);
       from++;
       for(d=0;d<6;d++){
         ux=vx+dx[d];
         uy=vy+dy[d];
         uz=vz+dz[d];
         if(ux>=0&&ux<n && uy>=0&&uy<m && uz>=0&&uz<k && !vis[ux][uy][uz]){
           if(g[ux][uy][uz])ans++;
           else{
               q[to++]=uz*m*n+uy*n+ux;
               vis[ux][uy][uz]=1;
           }
         }
       }            
   }
}          
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
   while(scanf("%d%d%d%d",&n,&m,&k,&l) && n){
      memset(vis,0,sizeof vis);
      memset(g,0,sizeof g);
      int pos,x,y,z;
      while(l--){
         scanf("%d",&pos);
          x=pos%n+1;
          y=(pos%(m*n))/n+1;
          z=pos/(m*n)+1;
          g[x][y][z]=1;
      }
      n+=2;m+=2;k+=2;
      ans=0;
      int i,j;
      for(i=0;i<m;i++)
        for(j=0;j<k;j++)if(!vis[0][i][j])bfs(j*m*n+i*n+0);
      for(i=0;i<m;i++)
        for(j=0;j<k;j++)if(!vis[n-1][i][j])bfs(j*m*n+i*n+n-1);
      for(i=0;i<n;i++)
        for(j=0;j<k;j++)if(!vis[i][0][j])bfs(j*m*n+i);
      for(i=0;i<n;i++)
        for(j=0;j<k;j++)if(!vis[i][m-1][j])bfs(j*m*n+(m-1)*n+i);
      for(i=0;i<n;i++)
        for(j=0;j<m;j++)if(!vis[i][j][0])bfs(j*n+i);
      for(i=0;i<n;i++)
        for(j=0;j<m;j++)if(!vis[i][j][k-1])bfs(j*n+i+(k-1)*m*n);
      printf("The number of faces needing shielding is %d.\n",ans);
   }
   return 0;
}

I - Hike on a Graph

bfs搜索~

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
#define N 51           
typedef long long ll;
int g[60][60],vis[60][60][60],d[60][60][60];     
int n,ans;  
void bfs(int px,int py,int pz){
    int q[60*60*60];
    int from=0,to=0,ux,uy,uz;
    q[to++]=px*N*N+py*N+pz;
    while(from<to){
       ux=q[from]/(N*N);
       uy=(q[from]%(N*N))/N;
       uz=q[from]%N;
       vis[ux][uy][uz]=1;
       if(ux==uy&&uy==uz){ans=d[ux][uy][uz];return;}
       from++;
       int i;
       for(i=1;i<=n;i++)if(g[ux][i]==g[uy][uz]&&!vis[i][uy][uz]){
           d[i][uy][uz]=min(d[i][uy][uz]>=0?d[i][uy][uz]:INF,1+d[ux][uy][uz]);
           q[to++]=i*N*N+uy*N+uz;
       }
       for(i=1;i<=n;i++)if(g[uy][i]==g[uz][ux]&&!vis[ux][i][uz]){
           d[ux][i][uz]=min(d[ux][i][uz]>=0?d[ux][i][uz]:INF,1+d[ux][uy][uz]);
           q[to++]=ux*N*N+i*N+uz;
       }
       for(i=1;i<=n;i++)if(g[uz][i]==g[ux][uy]&&!vis[ux][uy][i]){
           d[ux][uy][i]=min(d[ux][uy][i]>=0?d[ux][uy][i]:INF,1+d[ux][uy][uz]);
           q[to++]=ux*N*N+uy*N+i;
       }
    }
}
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
   int p1,p2,p3;
   while(scanf("%d",&n) && n){
       scanf("%d%d%d",&p1,&p2,&p3);
       memset(vis,0,sizeof vis);
       memset(d,-1,sizeof d);
       memset(g,0,sizeof g);
       int i,j;
       char s[5];
       for(i=1;i<=n;i++)
         for(j=1;j<=n;j++){
           scanf("%s",s);
           g[i][j]=s[0]-'a'+1;
         }
       ans=-1;
       d[p1][p2][p3]=0;
       bfs(p1,p2,p3);
       if(ans>=0)printf("%d\n",ans);
       else printf("impossible\n");
   }
   return 0;
}

G - Square Ice

模擬~我的做法是把逐個把0的狀態定下來然後print

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000

typedef long long ll;
int g[30][30];
char sq[100][100];           
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
   int m,t=1;
   while(scanf("%d",&m) && m){
      int i,j;
      memset(sq,0,sizeof sq);
      memset(g,0,sizeof g);
      for(i=0;i<m;i++)
        for(j=0;j<m;j++)scanf("%d",&g[i][j]);
      for(i=0;i<m;i++)
        for(j=0;j<m;j++)if(!g[i][j]){
           if(i && (g[i-1][j]==1||g[i-1][j]==6||g[i-1][j]==4))g[i][j]+=4;
           if(!j || (g[i][j-1]==6||g[i][j-1]==2||g[i][j-1]==-1))g[i][j]+=2;
        }
      int px,py;;
      for(i=0;i<m;i++)
        for(j=0;j<m;j++){
           px=i*4;py=j*4+2;
           sq[px][py]='O';
           if(g[i][j]==6||g[i][j]==4||g[i][j]==-1){sq[px-1][py]='|';sq[px-2][py]='H';}
           if(g[i][j]==2||g[i][j]==0||g[i][j]==-1){sq[px+1][py]='|';sq[px+2][py]='H';}
           if(g[i][j]==6||g[i][j]==2||g[i][j]==1){sq[px][py-1]='-';sq[px][py-2]='H';}
           if(g[i][j]==4||g[i][j]==0||g[i][j]==1){sq[px][py+1]='-';sq[px][py+2]='H';}
        }
      
      if(t>1)printf("\n");
      printf("Case %d:\n\n",t);
      for(i=0;i<4*m+3;i++)printf("*");
      printf("\n");
      for(i=0;i<=4*m-4;i++){
        printf("*");
        for(j=0;j<=4*m;j++){
           if(!sq[i][j])printf(" ");
           else printf("%c",sq[i][j]);
        }
        printf("*\n");
      }
      for(i=0;i<4*m+3;i++)printf("*");
      printf("\n");
      
      t++;
   }
   return 0;
}

E - Sorting It All Out

拓撲排序

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <stack>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
           
typedef long long ll;
int first[30],next[30*30],to[30*30],inc[30],g[30][30];  
int n,m,edge;
int q[30],res;
int toposort(){
    stack <int> s;
    int i,du[30];
    for(i=0;i<30;i++)du[i]=inc[i];
    res=0;
    for(i=1;i<=n;i++)if(!du[i])
      s.push(i);
    int u,e,v;
    while(!s.empty()){
       u=s.top();s.pop();
       q[res++]=u;
       e=first[u];
       while(e!=-1){
         du[to[e]]--;
         if(!du[to[e]])s.push(to[e]);
         e=next[e];
       }
    }
    if(res<n)return -1;
    for(i=0;i<n-1;i++)if(!g[q[i]][q[i+1]])return 0;
    return 1;
}
int main(){
//freopen("a.in","r",stdin);freopen("a.out","w",stdout);
   char str[10];
   while(scanf("%d%d",&n,&m) && n){
       int u,v,flag=0;
       memset(first,-1,sizeof first);
       memset(next,-1,sizeof next);
       memset(inc,0,sizeof inc);
       memset(g,0,sizeof g);
       edge=1;
       for(int i=1;i<=m;i++){
         scanf("%s",str);
         if(flag)continue;
         u=str[0]-'A'+1;
         v=str[2]-'A'+1;
         next[edge]=first[u];
         first[u]=edge;to[edge++]=v;
         inc[v]++;
         g[u][v]=1;
         res=0;
         flag=toposort();
         if(flag==1){
            printf("Sorted sequence determined after %d relations: ",i);
            for(int j=0;j<n;j++)printf("%c",'A'+q[j]-1);
            printf(".\n");
         }else if(flag==-1){
               printf("Inconsistency found after %d relations.\n",i);
         }
       }
       if(!flag)printf("Sorted sequence cannot be determined.\n");
   }
   return 0;
}

J - A Well-Formed Problem

這個是不是可以叫做蘑菇題了= =

一開始覺得hash,不過還是太麻煩改成了set……

模擬題實現起來也有很多可以學習的。做完看了一下watashi的代碼覺得簡直簡潔啊!

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <stack>
#include <set>
#include <string>
#include <cctype>
           
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
#define STACK_CLEAR while(!ele.empty())ele.pop();
#define SKIP(p) for(;*p==' ';p++);
#define GET(p)  for(;isalnum(*p)||*p=='-';p++);
#define EAT(p) while(*p!='"'&&*p!='\0')p++;
           
typedef long long ll;
stack <string> ele;
set <string> st;
set <string> attr;
const char START[]= "<?xml version=\"1.0\"?>" ;
const char END[]="<?end?>";
int root;
char* addnew(char* s){
      int shan=0;
      char *p=s+1;
      
      SKIP(p);
      if(*p=='/')++p,shan=1;
      attr.clear();
      
      SKIP(p);
      char *t0=p;
      GET(p);
      string t=string(t0,p);
      SKIP(p);
      
      while(*p!='>'&&*p!='/'&&*p){
            char *s0=p;
            GET(p);
            string ar=string(s0,p);
            /*for(;s0<p;s0++)printf("%c",*s0);
            printf("\n");*/
            
            if(attr.count(ar)>0)return NULL;
            attr.insert(ar);
            SKIP(p);
            if(*p!='=')return NULL;
            ++p;SKIP(p);
            if(*p!='"')return NULL;
            ++p;EAT(p);
            if(*p=='\0')return NULL;
            ++p;SKIP(p);
      }
      
      if(shan){
         if(ele.empty()||ele.top()!=t)return NULL;
         ele.pop();
         st.erase(t);
      }else if(*p=='/'){
            if(ele.empty())root++;
            ++p;SKIP(p);
      }
      else{
         if(st.count(t)>0)return NULL;
         if(ele.empty())root++;
         ele.push(t);
         st.insert(t);
      }
      if(*p!='>')return NULL;
      return p;
   }
int feed(char *p){
   char *s=p;
   while(*s){
      if(*s=='<'){
         s=addnew(s);
         if(s==NULL)return 0;
      }
      else s++;
   }
   return 1;
}
int main(){
   //freopen("a.in","r",stdin);freopen("a.out","w",stdout);
   char s[10010];
   gets(s);
   int flag=1;
   while(strcmp(s,END)){
      STACK_CLEAR;
      st.clear();
      gets(s);
      flag=1;
      root=0;
      while(strcmp(s,START)&&strcmp(s,END)){
         if(!flag||feed(s)==0)flag=0;
         gets(s);
      }
      if(!flag||root!=1||!ele.empty())printf("non well-formed\n");
       else printf("well-formed\n");
   }
   
   return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章