2016/12/10 Test Note

来源:互联网 发布:淘宝买家秀福利店铺名 编辑:程序博客网 时间:2024/06/10 01:00


Problem ID:1000   18岁生日 HDU 1201

分析:需要注意的是什么时候+1天 1.出生在闰年且在3月前 2.18岁时是闰年在2月后 ,什么时候没有生日 如果生日是闰年2月29日 18岁无法过生日 

代码:

#include<stdio.h>#include<string.h>bool Leap_year(int year){// bool 布尔型判断闰年 bool类型只有两个值true & false if((year%4==0 && year%100!=0)||(year%400==0))return true;elsereturn false;}int main(){int T,year,mon,day;scanf("%d",&T);while(T--){int sum=0;// 统计天数 scanf("%d-%d-%d",&year,&mon,&day);if( Leap_year(year) && mon==2 && day==29 ){// 如果生日是闰年2月29日 18岁无法过生日 printf("-1\n");continue;}// 需要注意的是什么时候+1天 1.出生在闰年且在3月前  2.18岁时是闰年在2月后 if( (Leap_year(year) && mon<3 ) || (Leap_year(year+18) && mon>=3 )) sum++;sum += 365; int i;for(i=year+1;i<year+18;i++){sum += 365;if(Leap_year(i))sum = sum+1;// 闰年366 }printf("%d\n",sum);}return 0;} 


Problem ID:1001   寻找素数对 HDU 1262

分析:先打素数表,输入中是一些偶整数M(5<M<=10000).所以数组开到10010,输出两个彼此最接近的素数 ,所以从中间开始向前寻找素数,如果 i 是素数且 m-i 也是素数输出并跳出循环

代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<iostream>using namespace std;const int maxn = 10000+10;int prime[maxn]={0};void set_table(){for(int i=2;i*i<maxn;i++){if(prime[i]==0){for(int j=2*i;j<maxn;j+=i)prime[j]=1;}}}int main(){int m;set_table();while(scanf("%d",&m)!=EOF ){int t=m/2;for(int i=t;i>=2;i--){if(prime[i]==0 && prime[m-i]==0){printf("%d %d\n",i,m-i);break;}}}return 0;} 


Problem ID:1002   最小公倍数 HDU 1108

分析:辗转相除法模板,递归实现

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}

代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<iostream>using namespace std;int gcd(int a,int b){return b==0?a:gcd(b,a%b);} int main(){int a,b;while(scanf("%d%d",&a,&b)!=EOF){//sort(a,a+2,cmp); printf("%d\n",a*b/gcd(a,b));}return 0;} 


Problem ID:1003   推箱子 HDU 1254

分析:需要判断人和箱子的相对位置,两个bfs嵌套,挪动一次箱子就判断一次人是否能到达使箱子挪动的地方。两次bfs,因为数据量不大,所以应该可以过

很棒的搜索题

需要注意的地方:
    1.人不能穿过箱子,所以每次在处理人的行进路径时需要把地图G中箱子处转换成1
    2.箱子不一定沿着到达目标点的最短路径前进
    3.需要开4维数组记录人和箱子的相对状态state,因为人在箱子4个方向是不同的状态会产生不同的后继状态,因此需要标记

代码:

/*Note:一开始想把问题分解成两个子问题1.用bfs找到最短路记录下路径 2.dfs判断人能否到达路径中每个点的前一个状态(即合法推箱子的状态) 后来发现有严重问题例如:17 64 1 1 1 1 10 1 0 0 0 10 1 0 1 0 10 2 0 1 0 30 0 0 1 0 10 0 0 0 0 10 0 0 0 0 1 我的思路只能选择两条最优路径中一条,然后进行判断,如果选择上面一条,那肯定是不对的,最合理的方法是选择下面的路径 所以这个思路是必错无疑挪动一次箱子就判断一次人是否能到达使箱子挪动的地方两次bfs,因为数据量不大,所以应该可以过 */#include<cstdio>  #include<cstring>  #include<queue> using namespace std;  //#define testint n,m;  int G[10][10];  int vis[10][10];  int state[9][9][9][9];  // 记录箱子和人的相对状态 int box_x,box_y,per_x,per_y,x_e,y_e;  // box person X 的位置 const int dx[]={-1,1,0,0};const int dy[]={0,0,-1,1};   struct point{    int x,y;  };  struct node{  // 存放现在的步数step 方向r box & per 的位置     int r,step;      struct point box;      struct point per;  };    bool check_per(int x,int y){// 判断person的行走是否合法      if(x<0 || x>=n || y<0 || y>=m || vis[x][y] )  return false;      return true;  }  bool judge_per(int x_s,int y_s,int x_e,int y_e){   // person能否从(x_s,y_s)到达(x_e,y_e)     queue<point>q;      point cur,next;        for(int i=0;i<n;i++)for(int j=0;j<m;j++)          vis[i][j]=G[i][j];            cur.x=x_s;cur.y=y_s;      vis[cur.x][cur.y]=1;      q.push(cur);        while(!q.empty()){          cur=q.front();          q.pop();                if(cur.x==x_e && cur.y==y_e)    return true;        for(int i=0;i<4;i++){              next.x=cur.x+dx[i];            next.y=cur.y+dy[i];              if(check_per(next.x,next.y)){            vis[next.x][next.y]=1;              q.push(next); }        }      }      return false;  }    bool check_box(int x,int y){      if(x<0 || x>=n || y<0 || y>=m || G[x][y])  return false;      return true;}  int judge_box(){      queue<node> q;      node cur,next;      cur.box.x=box_x;  cur.box.y=box_y;      cur.per.x=per_x;  cur.per.y=per_y;      cur.step=0;     for(int i=0;i<4;i++) // 找到开始时人和箱子的相对方向r         if(cur.box.x-cur.per.x==dx[i] && cur.box.y-cur.per.y==dy[i]){              cur.r=i;  break;          }    state[cur.per.x][cur.per.y][cur.box.x][cur.box.y]=1;      q.push(cur);    while(!q.empty()){          cur=q.front();    q.pop();          if(cur.box.x==x_e && cur.box.y==y_e)    return cur.step;          for(int i=0;i<4;i++){              bool ok=false;            if(cur.r==i)ok=true;  // 与人和箱子的相对方向相同时,开始推箱子             else{ // 换个方向尝试推箱子                 G[cur.box.x][cur.box.y]=1;                  ok=judge_per(cur.per.x,cur.per.y, cur.box.x-dx[i],cur.box.y-dy[i]);                  G[cur.box.x][cur.box.y]=0;              }              if(ok){            next.box.x=cur.box.x+dx[i];    next.box.y=cur.box.y+dy[i];              if( check_box(next.box.x,next.box.y) ){ // 检查箱子的移动是否合法             next.per.x=cur.box.x;next.per.y=cur.box.y;              if(!state[next.per.x][next.per.y][next.box.x][next.box.y]){            state[next.per.x][next.per.y][next.box.x][next.box.y]=1;              next.r=i;  // 记录下人和箱子的相对方向             next.step=cur.step+1;              q.push(next);          }        }        }        }      }      return -1;  }  int main(){  #ifdef testfreopen("Hdu 1254 推箱子 test case.txt","r",stdin);#endif    int T;    int aim_x,aim_y;      scanf("%d",&T);      while(T--){          scanf("%d%d",&n,&m);          for(int i=0;i<n;i++)          for(int j=0;j<m;j++){              scanf("%d",&G[i][j]);              if(G[i][j]==2)        {box_x=i;box_y=j;   G[i][j]=0;}              else if(G[i][j]==3)   {x_e=i  ;y_e=j;     G[i][j]=0;}              else if(G[i][j]==4)   {per_x=i;per_y=j;   G[i][j]=0;}          }          // 一开始时人就无法到达箱子的周围的某一个格子,这时就不需要搜索了,直接-1 bool ok=false;          for(int i=0;i<4;i++){     // 判断开始时是否在箱子周围             if(box_x-per_x==dx[i] && box_y-per_y==dy[i])  {              ok=true;  break;              }        }          if(!ok){     // 判断能否到达箱子周围             G[box_x][box_y]=1;    // 人无法穿过箱子**              for(int i=0;i<4;i++){                  aim_x=box_x+dx[i];aim_y=box_y+dy[i];                  ok=judge_per(per_x,per_y,aim_x,aim_y);                  if(ok){ per_x=aim_x;  per_y=aim_y;  break; }// 能到达箱子周围让person的位置更新一下即可             }             G[box_x][box_y]=0;          }          if(!ok) {printf("-1\n");continue;}          memset(state,0,sizeof(state));        printf("%d\n",judge_box());      }      return 0;  }


Problem ID:1004   唉,可爱的小朋友 HDU 2208

分析:一开始以为是匹配,GG,没认真读题......每个组至少有一个小球可以玩,而且每个组内不会有两个小朋友,相互不喜欢如果A喜欢和B一起玩,则B也喜欢和A一起玩。因为数据很小 n,m,k<=10 应该直接暴力遍历一遍的。对于第x人来说,要么加入之前的小组,要么单立一个小组。因此需要遍历之前每个小组中的所有人,全部喜欢才能假如小组,否则就是单立小组。

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;//#definetest int  n,m;int  rot[100],G[20][20];// G[][]:二元关系   rot[]:rot[i]=j  i的根是j bool ok;void dfs(int x,int y){// 判断第x个人是否能够加入之前的集合中  if(ok)  return;if(x==n){ ok=true; return; }if(y>m)  return;for(int i=0;i<x;i++){// 遍历之前所有集合,找到集合的根 if(rot[i]!=i)continue;int tag=1;// 遍历此集合 如果没有不喜欢的人则加入集合 for(int j=i;j<x && tag;j++) // 因为在输入的时候把关系全部存放在了上三角形中,所以只需要遍历上三角形中的二元关系即可 if(rot[j]==i)tag=G[j][x]; if(tag){rot[x]=i;dfs(x+1,y);rot[x]=x;// 将该点还原,以找到下一个该点的可能落脚点,以确保可以考虑到所有的可能} }dfs(x+1,y+1);   // 不能加入之前所有集合 -> y+1 }int main(){#ifdef testfreopen("Hdu 2208 唉,可爱的小朋友 test case.txt","r",stdin);#endifwhile(scanf("%d%d",&n,&m)!=EOF){memset(G,0,sizeof(G));ok=false;for(int i=0;i<n;i++){int k,t;scanf("%d",&k);rot[i]=i;for(int j=0;j<k;j++){scanf("%d",&t);G[i][t]=1;}}if(m>=n)printf("YES\n");// 一开始球比人多直接yeselse{dfs(0,0);printf("%s",ok?"YES\n":"NO\n"); } }return 0;}


Problem ID:1005   最少拦截系统 HDU 1257

分析:设置一个最大高度集合set_max[]如果下一个导弹比之前最大高度集合中某一个小,那就更新那个最大高度集合。如果扫描一遍后无法加入到之前的最大高度集,那么拦截系统数++

代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<iostream>using namespace std;const int maxn = 1000000;int info[maxn];int set_max[maxn];int main(){int n;while(scanf("%d",&n)!=EOF){int ans=1;scanf("%d",&info[0]);intk=0,j;// 标记最大集合set_max[k++]=info[0]; for(int i=1;i<n;i++){scanf("%d",&info[i]);for(j=0;j<k;j++){if(info[i]<set_max[j]){set_max[j]=info[i];break;}}if(j==k){// 找遍所有都没有,新加入set_max set_max[k]=info[i];k++; }}/*for(int i=0;i<k;i++)printf("%d ",set_max[i]);printf("\n");*/printf("%d\n",k);}return 0;}


Problem ID:1006   连连看   HDU 1175

分析:
    1.开始时就直接判断 如果起点处和目标点处数字不同,或则起点或终点有一个是0,直接no。  
    2.因为限定了最小转向次数,所以采用bfs单向搜,hdu 1728与之及其类似

代码:

/*Note:分析: 1.单方向BFS判断转折点,两次转折转折次数为3,从-1开始为2 2.一开始时就开始判断,如果起始点有一个是0或则起始点数字不同,则不需要受伤 */#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<iostream>using namespace std;//#define testconst int maxn = 1000+2;int G[maxn][maxn];int n,m;const int dx[]={-1,0,1,0};// 上 右 下 左 const int dy[]={0,1,0,-1};int vis[maxn][maxn];bool ok;struct point{int x,y,cnt;}s,e;bool check(int x,int y){return (x>=0 && x<n && y>=0 && y<m &&( G[x][y]==0 || ( x==e.x && y==e.y )))?true:false;}void bfs(){//一个方向搜到底queue<point> q;s.cnt=-1;q.push(s); vis[s.x][s.y]=1;int cnt;while(!q.empty()){point now = q.front(); q.pop();for(int i=0;i<4;i++){point t;t.x=now.x+dx[i];t.y=now.y+dy[i];while( check(t.x,t.y) ){if(!vis[t.x][t.y]){vis[t.x][t.y]=1;t.cnt=now.cnt+1;q.push(t);if(t.x==e.x && t.y==e.y && t.cnt<=2){// 转折次数不超过两次相当于转3次 ok=true;return ; }}t.x=t.x+dx[i],t.y=t.y+dy[i];// 继续一个方向搜 }}}}int main(){#ifdeftestfreopen("test.txt","r",stdin);#endifwhile(scanf("%d%d",&n,&m)!=EOF && n+m){memset(G,0,sizeof(G));for(int i=0;i<n;i++)for(int j=0;j<m;j++)scanf("%d",&G[i][j]);int q;scanf("%d",&q);for(int i=0;i<q;i++){ok=false;memset(vis,0,sizeof(vis));scanf("%d%d%d%d",&s.x,&s.y,&e.x,&e.y);s.x-- , s.y-- , e.x-- , e.y--;if((G[s.x][s.y]!=G[e.x][e.y]) || G[s.x][s.y]==0 || G[e.x][e.y]==0){ printf("NO\n"); continue; }bfs();if(ok)printf("YES\n");elseprintf("NO\n");}}return 0;} 


Problem ID:1007   画8   HDU 1256

分析:模拟,读题读题读题读题,认真认真认真认真。计算出上下圈高度宽度 s_h , x_h , L ,需要注意输出时后面不能有多余空格,否则会PE

代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<iostream>using namespace std;//#define testchar G[1000][1000];int main(){int n,h,kase=0;char str;#ifdef testfreopen("test.txt","r",stdin);freopen("output.txt","w",stdout);#endif cin>>n;while(n--){if(kase!=0)printf("\n");kase++;cin>>str >> h;int L  = h/6+1;// 宽度 int s_h=(h-3)/2;int x_h=(h-3)%2==0?(h-3)/2:(h-3)/2+1;memset(G,' ',sizeof(G));for(int j=0;j<2*L+x_h;j++)if(j>=L && j<L+x_h)G[0][j]=G[s_h+1][j]=G[h-1][j]=str;for(int i=0;i<h;i++){if(i==0 || i==s_h+1 || i==h-1)continue;for(int j=0;j<2*L+x_h;j++)if(j>=L && j<L+x_h)continue;elseG[i][j]=str;}for(int i=0;i<h;i++){if(i==0 || i==s_h+1 || i==h-1){for(int j=0;j<L+x_h;j++)printf("%c",G[i][j]);printf("\n");}else{for(int j=0;j<2*L+x_h;j++)printf("%c",G[i][j]);printf("\n");}}} return 0;}



Problem ID:1008   The calculation of GPAHDU 1202

分析:成绩是实型,需要注意的是89.5这样的成绩,多组测试数据多组测试数据多组测试数据多组测试数据!!!%$#@ 

代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<iostream>using namespace std;//#define testconst int maxn = 10000;int main(){int n;#ifdef testfreopen("test.txt","r",stdin);#endifwhile(scanf("%d",&n)!=EOF){double sum,m;sum=m=0;int flag=0;for(int i=0;i<n;i++){double s,p;cin>>s>>p;if(p==-1){flag++;continue;}m+=s;if(p>=90)p=4;else if((p>=80)&&(p<90))p=3;else if((p>=70)&&(p<80))p=2;else if((p>=60)&&(p<70))p=1;elsep=0;sum += p*s;} if(sum==0 || flag==n)printf("-1\n");elseprintf("%.2lf\n",sum/m);}return 0;}


Problem ID:1000   悼念512汶川大地震遇难同胞——老人是真饿了   HDU 2187

分析:最简单的思路,先挑最便宜的买,能买光就买光,能买多少就买多少 

代码:

#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<iostream>using namespace std;struct Node{int p,h;}info[1000+10];bool cmp(Node a,Node b){if(a.p<b.p)return true;elsereturn false;}int main(){int n,m,c;scanf("%d",&c);while(c--){double ans=0;scanf("%d%d",&n,&m);// n是钱数 for(int i=0;i<m;i++)scanf("%d%d",&info[i].p,&info[i].h);sort(info,info+m,cmp);for(int i=0;i<m;i++){if(n-info[i].p*info[i].h>=0){ans += info[i].h;n -= info[i].p*info[i].h;}else{ans += n*1.0/info[i].p;n=0;}}printf("%.2lf\n",ans);} return 0;} /*210 23 34 47 23 34 4*/





0 0
原创粉丝点击