狗狗40题~ (Volume B)

H - Sorting Slides

应该是个二分匹配的模板题的,但我还不会写 = =

好在数据规模小,就用贪心的方法水过了(没加vis判冲突wa了几发,从此开始艰难的没有1A 的生活哭

#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;
struct slide{
   int x1,x2,y1,y2;
}rec[50];      
int g[100][100],d[100],ans[50],vis[100];          
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
   int n,cs=1;
   while(scanf("%d",&n) && n){
      for(int i=0;i<n;i++)scanf("%d%d%d%d",&rec[i].x1,&rec[i].x2,&rec[i].y1,&rec[i].y2);
      int x,y;
      memset(d,0,sizeof d);
      memset(g,0,sizeof g);
      memset(vis,0,sizeof vis);
      memset(ans,-1,sizeof ans);
      for(int i=0;i<n;i++){
         scanf("%d%d",&x,&y);
         for(int j=0;j<n;j++)if(x<rec[j].x2&&x>rec[j].x1&&y<rec[j].y2&&y>rec[j].y1){
             g[i][j+n]=1;d[i]++;
             d[j+n]++;
         }
      }
      int flag=1;
      while(flag){
         int i,j,i0,j0;
         flag=0;
         for(i=0;i<n;i++)if(!vis[i]&&d[i]==1)
            {flag=1;break;}
         if(flag){
            for(j=n;j<2*n;j++)if(!vis[j]&&g[i][j])break;
            i0=i,j0=j;
            ans[j0-n]=i0;
            vis[i0]=vis[j0]=1;
            g[i0][j0]=0;d[i0]--;d[j0]--;
            for(i=0;i<n;i++)if(g[i][j0])d[i]--,g[i][j0]=0;
            continue;
         }
         for(j=n;j<2*n;j++)if(!vis[j]&&d[j]==1)
            {flag=1;break;}
         if(flag){
            for(i=0;i<n;i++)if(!vis[i]&&g[i][j])break;
            i0=i;j0=j;
            ans[j0-n]=i0;
            vis[i0]=vis[j0]=1;
            g[i0][j0]=0;d[i0]--;d[j0]--;
            for(j=n;j<2*n;j++)if(g[i0][j])d[j]--,g[i0][j]=0;
            continue;
         }
      }
      int cnt=0;
      printf("Heap %d\n",cs++);
      for(int i=0;i<n;i++)if(ans[i]>=0)
         {if(cnt)printf(" ");printf("(%c,%d)",'A'+i,ans[i]+1);cnt++;}
      if(!cnt)printf("none");
      printf("\n\n");
      }
   return 0;
}

A - Triangle Encapsulation

不能更水。

#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;
struct point {
    int x,y;
    struct point operator -(const struct point b){
        struct point c;
        c.x=x-b.x;c.y=y-b.y;
        return c;         
    }
}p[5];
int cmp(struct point a,struct point b){
   if(a.y-b.y)return a.y>b.y;
   return a.x<b.x;
}
int g[20][20];
int cross(struct point a,struct point b){
   return a.x*b.y-a.y*b.x;
}        
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
    printf("Program 4 by team X\n");
   while(scanf("%d%d",&p[0].x,&p[0].y)!=EOF){
      for(int i=1;i<3;i++)scanf("%d%d",&p[i].x,&p[i].y);
      struct point pi;
      memset(g,0,sizeof g);
      int xmin=18,ymin=18,ymax=0,xx[20]={0};
      for(pi.x=-9;pi.x<=9;pi.x++)
       for(pi.y=-9;pi.y<=9;pi.y++){
           int c1=0,c2=0;
           for(int i=0;i<3;i++){
              if(cross(pi-p[i],pi-p[(i+1)%3])<0)c1++;
              if(cross(pi-p[i],pi-p[(i+1)%3])>0)c2++;
           }
           if(c1==3||c2==3){
              g[pi.x+9][pi.y+9]=1;
              xmin=min(xmin,pi.x+9);
              xx[pi.y+9]=max(xx[pi.y+9],pi.x+9);
              ymin=min(ymin,pi.y+9);
              ymax=max(ymax,pi.y+9);
           }
       }
      int x,y;
      for(y=ymax;y>=ymin;y--){
        for(x=xmin;x<=xx[y];x++){
           if(x>xmin)printf(" ");
           if(g[x][y])printf("(%2d,%3d)",x-9,y-9);
           else printf("        ");
        }
        printf("\n");
      }
      printf("\n");
   }
   printf("End of program 4 by team X\n");
   return 0;
}

G - Reflections

几何题。解析算错很多次,其实就是算交点和关于直线对称。用向量不容易错。

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <utility>
           
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 eps 1e-6
           
typedef long long ll;
int n,ans[30],cur;
struct point{
   double x,y;
};
struct circle{
   double x,y,r;
}cir[30];
struct line{
   double x0,y0,dx,dy;
}ori;
int sgn(double x){
   if(x>eps)return 1;
   if(x<-eps)return -1;
   return 0;
}
pair <double,int> inter(struct line now){
   double a,b,c,del,t1,t2,t=-1;
   int use=-1;
   for(int i=1;i<=n;i++){
      a=now.dx*now.dx+now.dy*now.dy;
      b=now.dx*(now.x0-cir[i].x)+now.dy*(now.y0-cir[i].y);
      c=(now.x0-cir[i].x)*(now.x0-cir[i].x)+(now.y0-cir[i].y)*(now.y0-cir[i].y)-cir[i].r*cir[i].r;
      del=b*b-a*c;
      if(sgn(del)<=0)continue;
      t1=(-b-sqrt(del))/a;
      t2=(-b+sqrt(del))/a;
      if(sgn(t1)>0){
         if(t==-1||t>t1)t=t1,use=i;
      }
      else if(sgn(t2)>0){
         if(t==-1||t>t2)t=t2,use=i;
      }
   }
   return make_pair(t,use);
}    
void work(struct line now){
   if(cur>10)return;
   double t=inter(now).first;
   if(t<=0)return;
   int i0=ans[cur++]=inter(now).second;
  
   /* 求对称射线 */ 
   double x,y,xx,yy;
   x=now.x0+t*now.dx;
   y=now.y0+t*now.dy;
   if(sgn(now.dy*(x-cir[i0].x)-now.dx*(y-cir[i0].y))==0){
       now.x0=x;now.y0=y;
       now.dx=-now.dx;now.dy=-now.dy;
       work(now);
       return;
   }
   xx=-((x-cir[i0].x)*now.dx+(y-cir[i0].y)*now.dy)/cir[i0].r;
   yy=((x-cir[i0].x)*now.dy-(y-cir[i0].y)*now.dx)/cir[i0].r;
   now.x0=x;now.y0=y;
   now.dx=(xx*(x-cir[i0].x)-yy*(y-cir[i0].y))/cir[i0].r;
   now.dy=(xx*(y-cir[i0].y)+yy*(x-cir[i0].x))/cir[i0].r;
   work(now);
}      

int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout); 
   int cs=1;
   while(scanf("%d",&n) && n){
       int i;
       for(i=1;i<=n;i++)scanf("%lf%lf%lf",&cir[i].x,&cir[i].y,&cir[i].r);
       scanf("%lf%lf%lf%lf",&ori.x0,&ori.y0,&ori.dx,&ori.dy);
       cur=0;
       work(ori);
       printf("Scene %d\n",cs++);
       for(i=0;i<cur&&i<10;i++)printf("%d ",ans[i]);
       if(cur>10)printf("...\n\n");
       else printf("inf\n\n");
   }
   return 0;
}

C - Robbery

一开始有点不敢写,想了一下其实每个时间点只和前后两个点有关,所以正着跑一次再倒着check一遍就确定了。

#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 w,h,T,n;
int g[105][105][105];  
struct message{
   int t,l,u,r,d;
}mes[105];
struct answer{
   int t,x,y;
}ans[105];
int cmp(struct message a,struct message b){
   return a.t<b.t;
}
void direct(){
   int k=0;
      memset(g,-1,sizeof g);
      memset(g[1],0,sizeof g[1]);
      for(int t=1;t<=T;t++){
        //to expand reachable area.
        if(t>1)
        for(int i=1;i<=h;i++)
           for(int j=1;j<=w;j++)if(!g[t-1][i][j]){
                 g[t][i][j]=0;
                 if(i>1)g[t][i-1][j]=0;
                 if(j>1)g[t][i][j-1]=0;
                 if(i<h)g[t][i+1][j]=0;
                 if(j<w)g[t][i][j+1]=0;
           }
        //to receive the messge.    
        for(;k<n&&mes[k].t==t;k++){
           for(int i=mes[k].u;i<=mes[k].d;i++)
             for(int j=mes[k].l;j<=mes[k].r;j++)
                g[t][i][j]=-1;
        }
        
      }
}
void inverse(){
   int k=n-1;
   for(int t=T-1;t>0;t--){
      for(int i=1;i<=h;i++)
        for(int j=1;j<=w;j++)if(!g[t][i][j]){
            if(!g[t+1][i][j])continue;
            if(i>1&&!g[t+1][i-1][j])continue;
            if(j>1&&!g[t+1][i][j-1])continue;
            if(i<h&&!g[t+1][i+1][j])continue;
            if(j<w&&!g[t+1][i][j+1])continue;
            g[t][i][j]=-1;
        }
   }
}
int main(){
    //freopen("r.in","r",stdin);freopen("r.out","w",stdout);
   int cs=1;
   while(scanf("%d%d%d",&w,&h,&T) && w){
      scanf("%d",&n);
      for(int i=0;i<n;i++)
         scanf("%d%d%d%d%d",&mes[i].t,&mes[i].l,&mes[i].u,&mes[i].r,&mes[i].d);
      sort(mes,mes+n,cmp);
      direct();
      inverse();
      printf("Robbery #%d:\n",cs++);
      int res=0,flag=1;
      for(int t=1;t<=T;t++){
        int cn=0,x,y;
        for(int i=1;i<=h;i++)
          for(int j=1;j<=w;j++)if(!g[t][i][j])x=i,y=j,cn++;
        if(!cn){flag=0;break;}
        if(cn==1)ans[res].t=t,ans[res].x=x,ans[res++].y=y;
      }
      if(!flag)printf("The robber has escaped.\n\n");
      else{
         if(!res)printf("Nothing known.\n\n");
         else{
            for(int i=0;i<res;i++)printf("Time step %d: The robber has been at %d,%d.\n",ans[i].t,ans[i].y,ans[i].x);
            printf("\n");
         }
      }
   }
   return 0;
}

E - Triangle War

状压dp,极大极小算法。

另外有个坑点是每次不一定要把能取的三角形位置都取完。。

#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 edge[15][15],tri[10]={7,152,52,352,34304,3200,71680,12544,155648};  
int dp[1<<18];
int check(int sta){
   int ans=0;
   for(int i=0;i<9;i++)if((sta&tri[i])==tri[i])ans++;
   return ans;    
}
void dfs(){
   int s=(1<<18)-1;
   dp[s]=0;
   for(s=s-1;s>=0;s--){
      int ori=check(s),cn,maxdp=-10;
      for(int i=0;i<18;i++)if(!((1<<i)&s)){
         int to=(1<<i)|s;
         int temp=check(to)-ori;
         if(temp)temp+=dp[to];
         else temp-=dp[to];
         maxdp=max(maxdp,temp);
      }
      dp[s]=maxdp;
   }
}
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
   int t,gm,G;
   edge[1][2]=1;edge[1][3]=1<<1;
   edge[2][3]=1<<2;edge[2][4]=1<<3;edge[2][5]=1<<4;
   edge[3][5]=1<<5;edge[3][6]=1<<6;
   edge[4][5]=1<<7;edge[4][7]=1<<9;edge[4][8]=1<<10;
   edge[5][6]=1<<8;edge[5][8]=1<<11;edge[5][9]=1<<12;
   edge[6][9]=1<<13;edge[6][10]=1<<14;
   edge[7][8]=1<<15;edge[8][9]=1<<16;edge[9][10]=1<<17;
   dfs();
   scanf("%d",&t);
   while(t--){
      scanf("%d",&G);
      for(gm=1;gm<=G;gm++){
         int m,sta=0,u,v,turn=0;
         int a[2]={0};
         scanf("%d",&m);
         for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            int ori=check(sta);
            sta+=edge[u][v];
            ori=check(sta)-ori;
            a[turn]+=ori;
            if(!ori)turn=!turn;
         }
         printf("Game %d: ",gm);
         a[turn]+=dp[sta];
         if(a[0]>a[1])printf("A wins.\n");
         else printf("B wins.\n");
      }
      if(t)printf("\n");
   }
   return 0;
}

D - Dreisam Equations

就是暴力加表达式计算。一直SegmentationFault不明所以,发现是代表符号的值取的不好会和数值冲突=_=

#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#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
#define zuokuo 200000000
#define youkuo 200000001
#define kong 200000009
#define jia -200000000
#define jian -200000001
#define cheng -200000002
           
typedef long long ll;
char eq[1000];
int q[1000],res;
int lf;
stack <int> a;
stack <int> s;
int solve(int cur){
   if(cur==res){
      while(!a.empty())a.pop();
      while(!s.empty())s.pop();
      for(int i=0;i<res;i++){
         if(q[i]>-200000000&&q[i]<200000000){
            if(s.empty()||s.top()==zuokuo)a.push(q[i]);
            else{
                  int u=a.top();a.pop();
                  if(s.top()==jia)a.push(u+q[i]);
                  if(s.top()==jian)a.push(u-q[i]);
                  if(s.top()==cheng)a.push(u*q[i]);
                  s.pop();
            }
         }
         else if(q[i]==youkuo){
              if(s.empty()||s.top()!=zuokuo)return 0;
              s.pop();
              if(s.empty()||s.top()==zuokuo)continue;
              int u=a.top();a.pop();
              int v=a.top();a.pop();
              if(s.top()==jia)a.push(v+u);
              if(s.top()==jian)a.push(v-u);
              if(s.top()==cheng)a.push(v*u);
                    s.pop();
         }
         else s.push(q[i]);
      }
      if(a.top()==lf)return 1;
      else return 0;
   }
   if(q[cur]!=kong)return solve(cur+1);
   for(int i=cheng;i<=jia;i++){
      q[cur]=i;
      if(solve(cur+1))return 1;
      q[cur]=kong;
   }
   return 0;
}           
int main(){
   int cs=1;
   while(gets(eq) && eq[0]!='0'){
      sscanf(eq,"%d",&lf);
      res=0;
      int i;
      for(i=0;eq[i]!='=';i++);
      for(i++;eq[i]!='\0';i++){
         for(;eq[i]==' ';i++);
         if(eq[i]=='('){q[res++]=zuokuo;continue;}
         if(eq[i]==')'){q[res-1]=youkuo;q[res++]=kong;continue;}
         int num=0;
         while(eq[i]>='0'&&eq[i]<='9'){
            num=num*10+eq[i]-'0';
            i++;
         }
         q[res++]=num;
         q[res++]=kong;
         i=i-1;
      }
      res=res-1;
      
      printf("Equation #%d:\n",cs++);
      if(solve(0)==0)printf("Impossible\n\n");
      else{
         printf("%d=",lf);
         for(int i=0;i<res;i++){
            if(q[i]==zuokuo)printf("(");
            else if(q[i]==youkuo)printf(")");
            else if(q[i]==jia)printf("+");
            else if(q[i]==jian)printf("-");
            else if(q[i]==cheng)printf("*");
            else printf("%d",q[i]);
         }
         printf("\n\n");
      }
      
   }
   return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值