2013腾讯编程马拉松初赛第五场(3月25日)

来源:互联网 发布:java开发界面 编辑:程序博客网 时间:2024/05/22 10:25

4525 威威猫系列故事——吃鸡腿

Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Problem Description
  威威猫不是一只普通的猫,普通的猫喜欢吃鱼,但威威猫最喜欢吃鸡腿。他每天都在不停的吃啊吃,吃了一只又一只鸡腿。现在他遇到了一个难题,如果他的体重太胖那么他的主人就不给他吃鸡腿了,所以他需要你的帮助。
  威威猫的身体由n个器官构成,由于他的身体很特殊所以他的增长也很特殊(不要问为什么,喜欢吃鸡腿的猫已经够奇怪了)。他的增长有个k1和k2系数,而且每天的增长量和前一天有关,我们假设这n个器官在第i天的数值分别是a(i,1), a(i,2), a(i,3) …… a(i,n),那么,第i+1天他每个器官的数值就会变成:
  a(i+1,1) = k1 * a(i,1) + k2 * a(i,2)
  a(i+1,2) = k1 * a(i,2) + k2 * a(i,3)
  ……
  a(i+1,n) = k1 * a(i,n) + k2 * a(i,1)
  威威猫的体重等于他的所有器官的数值之和,并且他还拥有一个特殊的机能,就是会自动检测自己的体重,如果他的体重比K大,那么就会自动停止生长(为了每天都能吃到鸡腿),由于威威猫的特殊身体构造他的体重是可能会变成负数的。
  现在我给你n个器官的初始数值和他的增长系数k1,k2,请问他几天之后会停止生长,如果他永远无法停止生长那么就输出”inf”。(引号不用输出)
Input
输入数据第一行是一个正整数T,表示有T组测试数据;
每组数据的第一行包含4个数字n,k1,k2,k,代表威威猫有n个器官,他的生长系数是k1,k2,当体重超过k的时候他就停止生长。
接下来的一行是n个数ai,代表威威猫每个器官第一天的数值是多少。
[Technical Specification]
T <= 100
1 <= n <= 10000
-100 <= k1, k2 <= 100
1 <= k <= 10 ^ 18
1 <= ai <= 1000(1 <= i <= n)
Output
对于每组测试数据,请首先输出”Case #X: “,X代表测试用例的编号,然后输出一个数ans,代表ans天之后他会停止生长,如果不会停止就输出inf.
具体可参见sample output。
Sample Input
2
5 1 1 10
1 1 1 1 1
5 1 1 500
1 1 1 1 1
Sample Output
Case #1: 2
Case #2: 7
Source
2013腾讯编程马拉松初赛第五场(3月25日)

#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;int T,Case=0;int main(){    cin>>T;    while(T--){        ++Case;        int n,K1=0,K2=0;        __int64 sum1=0,sum=0,K;        scanf("%d%d%d%I64d",&n,&K1,&K2,&K);        __int64 tmp;        for(int i=1;i<=n;++i){            scanf("%I64d",&tmp);            sum+=tmp;        }        sum1=sum;        printf("Case #%d: ",Case);        for(int i=0;;++i){            if(sum1>K){ printf("%d\n",i); break; }            sum=sum1,sum1=sum*(K1+K2);            if((sum >0 &&(K1+K2)>0 && sum1 <0)) { printf("%d\n",i+1); break; }            if(sum<0&&(K1+K2)<0&&sum1<0){ printf("%d\n",i+1); break; }            if(i>100000) { printf("inf\n"); break; }        }    }    return 0;}

4526 威威猫系列故事——拼车记

Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1381 Accepted Submission(s): 478
Problem Description
  话说威威猫有一次去参加比赛,虽然学校离比赛地点不太远,但威威猫还是想坐出租车去。大学城的出租车总是比较另类,有“拼车”一说,也就是说,你一个人坐车去,还是一堆人一起,总共需要支付的钱是一样的(每辆出租上除司机外最多坐下4个人)。刚好那天同校的一群Acmer在校门口扎堆了,大家果断决定拼车去赛场。
  问题来了,一辆又一辆的出租车经过,但里面要么坐满了乘客,要么只剩下一两个座位,众Acmer都觉得坐上去太亏了,威威猫也是这么想的。
  假设N名Acmer准备拼车,此时为0时刻,从校门到目的地需要支付给出租车师傅D元(按车次算,不管里面坐了多少Acmer),假如S分钟后恰能赶上比赛,那么S分钟后经过校门口的出租车自然可以忽略不计了。现在给出在这S分钟当中经过校门的所有的K辆出租车先后到达校门口的时间Ti 及里面剩余的座位Zi (1 <= Zi <= 4),Acmer可以选择上车几个人(不能超过),当然,也可以选择上0个人,那就是不坐这辆车。
  俗话说,时间就是金钱,这里威威猫把每个Acmer在校门等待出租车的分钟数等同于花了相同多的钱(例如威威猫等待了20分钟,那相当于他额外花了20元钱)。
  在保证所有Acmer都能在比赛开始前到达比赛地点的情况下,聪明的你能计算出他们最少需要花多少元钱么?
Input
输入第一行为T,表示有T组测试数据。每组数据以四个整数N , K , D , S开始,具体含义参见题目描述,接着K行,表示第i辆出租车在第Ti分钟到达校门,其空余的座位数为Zi(时间按照先后顺序)。
[Technical Specification]
T <= 50
N <= 100
K <= 100
D <= 100
S <= 100
1 <= Zi <= 4
1<= T(i) <= T(i+1) <= S
Output
对于每组测试数据,输出占一行,如果他们所有人能在比赛前到达比赛地点,则输出一个整数,代表他们最少需要花的钱(单位:元),否则请输出“impossible”。
Sample Input
1
2 2 10 5
1 1
2 2
Sample Output
14
Source
2013腾讯编程马拉松初赛第五场(3月25日)

//这是个背包问题#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<cstdio>using namespace std;#define INF 0x3f3f3f3fconst int MAXN = 110;int n,K,D,s,dp[MAXN][MAXN];int cas,t[MAXN],z[MAXN];int main(){    scanf("%d",&cas);    while(cas--){        scanf("%d%d%d%d",&n,&K,&D,&s);        t[0]=0;        for(int i=1;i<=K;++i) scanf("%d%d",&t[i],&z[i]);//K 个车辆的信息        for(int i=0;i<MAXN;++i) dp[i][0]=0;        for(int i=0;i<MAXN;++i)            for(int j=1;j<MAXN;++j) dp[i][j]=INF;        for(int i=1;i<=K;++i)            for(int j=1;j<=n;++j){                dp[i][j]=dp[i-1][j];                for(int k=1;k<=z[i];++k)                    dp[i][j]=min(dp[i][j],dp[i-1][j-k]+t[i]*k+D);            }        if(dp[K][n]==INF) printf("impossible\n");        else printf("%d\n",dp[K][n]);    }    return 0;}

4527 小明系列故事——玩转十滴水

Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 774 Accepted Submission(s): 314
Problem Description
  小明最近喜欢上了一个名为十滴水的游戏。
  这里写图片描述
  游戏是在一个6*6的方格内进行的,每个格子上有一滴水或者没有水滴。水滴分为四个等级1~4。初始时你有十滴水,通过把水加入格子内的水滴,会让水滴升1级。你也可以把水放到空格子内,这样会在这个格子里面产生一个1级的水滴。当水滴等级大于4时则会爆裂为四个小水滴,并向四个方向飞溅。每个飞溅的小水滴碰到其他水滴后会融入其中,使其升一级或者爆裂,以此类推。飞溅的小水滴互不干扰,运动速度相等(1秒可以移动一个格子的距离)。水滴爆裂后就消失掉了。
  
Input
题目包含多组测试用例;
对于每组数据,首先是6行,每行有6个整数数字,每个数字的范围为0~4;当数字为0时,表示空格子,当数字为1~4时,表示1~4级的水滴;
然后第七行是一个整数m,表示有m个操作;接下来是m行,每行有两个整数x, y ,表示在(x,y)放入一滴水。
特别说明:每次都是在全部的水滴静止后才进行下一次操作,也就是说只有在方格内没有任何飞溅的小水滴时才能放入一滴水。
[Technical Specification]
1 <= m <= 10
1 <= x, y <= 6
Output
对于每组测试数据,请输出m个操作之后6*6方格内水滴的样子,每组数据的输出后面跟着一个空行。
Sample Input
0 0 0 4 0 4
0 0 0 0 0 0
1 0 0 4 0 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 1 0 0
1
1 6
0 0 0 4 0 4
0 2 0 4 0 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1
1 6
2 2 0 2 0 3
3 3 0 1 3 1
2 2 2 4 0 4
2 4 4 2 2 3
3 3 2 4 0 1
1 3 4 3 0 1
6
5 3
5 3
3 3
3 2
2 1
6 3
Sample Output
0 0 0 0 0 0
0 0 0 0 0 0
2 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 2 0 0
0 0 0 0 0 0
0 3 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 4 0 2 0 3
0 0 0 4 3 2
0 0 0 0 0 0
0 0 0 0 4 4
0 0 0 0 0 4
4 0 0 0 0 3
Hint
第一组数据:
(1,6)爆裂,然后在第二秒(1,4)(2,6)爆裂,在第四秒,两滴水同时到达(3,4), (3,4)变成了6,爆裂,然后在第七秒(3,1)(6,4)变成了2。
Source
2013腾讯编程马拉松初赛第五场(3月25日)

//宽搜  深搜比较难处理同时性#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<queue>using namespace std;int bo[7][7],m,flag;struct Node{ int x,y,f; }s,t;int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};queue<Node> q,qq;inline bool Judge(int x,int y){ return x>=1&&x<=6&&y>=1&&y<=6; }void Get_ID(int x,int y){    bo[x][y]=0;    for(int i=0;i<4;++i){        s.x=x+dx[i],s.y=y+dy[i],s.f=i;        if(Judge(s.x,s.y)) qq.push(s);    }}void BaoZha(int x,int y){    while(!q.empty()) q.pop();    while(!qq.empty()) qq.pop();    bo[x][y]=0;    for(int i=0;i<4;++i){        s.x=x+dx[i],s.y=y+dy[i],s.f=i;        if(Judge(s.x,s.y)) q.push(s);    }    while(1){        flag=0;        while(!q.empty()){            flag=1;            s=q.front();q.pop();            if(bo[s.x][s.y]==0){                t.x=s.x+dx[s.f],t.y=s.y+dy[s.f],t.f=s.f;                if(Judge(t.x,t.y)) qq.push(t);            }            if(bo[s.x][s.y]>0) ++bo[s.x][s.y];        }        for(int i=1;i<=6;++i)            for(int j=1;j<=6;++j)                if(bo[i][j]>4) flag=1,Get_ID(i,j);        swap(q,qq);        if(!flag) break;    }}int main(){    while(~scanf("%d",&bo[1][1])){        for(int i=1;i<=6;++i)            for(int j=1;j<=6;++j)                if(i==1&&j==1) continue;                else scanf("%d",&bo[i][j]);        scanf("%d",&m);        for(int x,y,i=1;i<=m;++i){            scanf("%d %d",&x,&y);            if((++bo[x][y])>4) BaoZha(x,y);        }        for(int i=1;i<=6;++i){            for(int j=1;j<=6;++j)                if(j==1) printf("%d",bo[i][j]);                else printf(" %d",bo[i][j]);            printf("\n");        }        printf("\n");    }    return 0;} 

4528 小明系列故事——捉迷藏

Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1815 Accepted Submission(s): 542
Problem Description
  小明的妈妈生了三个孩子,老大叫大明, 老二叫二明, 老三…, 老三自然就叫小明了。
  一天,小明的妈妈带小明兄弟三人去公园玩耍,公园里面树木很多,有很多地方可以藏身, 于是他们决定玩捉迷藏。经过几轮的猜拳后,第一轮是小明来找其他两个人,游戏规则很简单:
  只要小明可以在规定的时间内找到他们就算小明获胜,并且被发现的两个人猜拳决定谁在下一轮负责找人;如果在规定的时间内只找到一个人,那么没有被发现的人获胜,被找到的人下一轮负责找人;如果在规定的时间内一个人都没有找到,则小明失败了,下一轮还是他来找人。现在小明想知道,在规定时间内,自己是否可以找到所有的人,现在他想请你来帮忙计算一下。
  为了简单起见,把公园看成是n行m列的矩阵,其中’S’表示小明,’D’表示大名,’E’表示二明,’X’表示障碍物,’.’表示通路。这里,我们把发现定义为,可以直接看到对方, 也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方。并且假设,大明,二明藏好以后就不会再改变位置,小明每个单位时间可以从当前的位置走到相邻的四个位置之一,并且不会走出公园。
Input
测试数据第一行是一个正整数T,表示有T组测试数据。
每一组测试数据首先是三个正整数n,m,t,分别表示行数、列数和规定的时间,接下来n行,每行m个上述的字符,并且保证有且只有一个’S’,一个’E’,一个’D’。
[Technical Specification]
T < 200
3 <= n, m <= 100
0 <= t <= 100
Output
每组先输出一行Case c:(c表示当前的组数,从1开始计数);
接下来一行,如果小明可以在规定时间内找到所有的人,则输出最少需要的时间,否则输出-1。
Sample Input
3
5 6 3
XXD…
….E.
….X.
….S.
……
5 6 3
XDX…
….E.
……
….S.
……
5 6 8
XXDX..
.XEX..
……
….S.
……
Sample Output
Case 1:
-1
Case 2:
3
Case 3:
-1
Source
2013腾讯编程马拉松初赛第五场(3月25日)

//搜索#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;#define MAXN 105char map[MAXN][MAXN];int vis[MAXN][MAXN][2][2];struct Node{    int x,y,step,flag1,flag2;    Node (int x=0,int y=0,int step=0,int flag1=0,int flag2=0):        x(x),y(y),step(step),flag1(flag1),flag2(flag2) { }}now,nex;queue<Node> q,qq;int T,n,m,t;inline void read(int &x){    x=0; int f=1; char c=getchar();    while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }    while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;}int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};inline bool Judge(int x,int y,int f1,int f2){    return x>=1&&x<=n&&y<=m&&y>=1&&map[x][y]!='E'&&map[x][y]!='D'        &&map[x][y]!='X'&&vis[x][y][f1][f2]==0;}void solve(int sx,int sy){    q.push(Node(sx,sy,0,0,0));    vis[sx][sy][0][0]=1;    while(!q.empty()){        now=q.front();q.pop();        int x=now.x,y=now.y,step=now.step;        for(int i=x+1;i<=n;++i)            if(map[i][y]=='E') { now.flag2=1;break;}            else if(map[i][y]=='D') { now.flag1=1;break;}            else if(map[i][y]=='X') break;        for(int i=x-1;i>=1;--i)            if(map[i][y]=='E') { now.flag2=1;break;}            else if(map[i][y]=='D') { now.flag1=1;break;}            else if(map[i][y]=='X') break;        for(int i=y+1;i<=m;++i)            if(map[x][i]=='E') { now.flag2=1;break;}            else if(map[x][i]=='D') { now.flag1=1;break;}            else if(map[x][i]=='X') break;        for(int i=y-1;i>=1;--i)            if(map[x][i]=='E') { now.flag2=1;break;}            else if(map[x][i]=='D') { now.flag1=1;break;}            else if(map[x][i]=='X') break;        if(now.flag1==1&&now.flag2==1){ printf("\n%d\n",now.step); return ; }        for(int i=0;i<4;++i){            nex=now;            nex.x=now.x+dx[i] , nex.y=now.y+dy[i] , nex.step=now.step+1;            if(nex.step>t) break;            if(Judge(nex.x,nex.y,nex.flag1,nex.flag2)) {                vis[nex.x][nex.y][nex.flag1][nex.flag2]=1;                q.push(nex);            }        }    }    printf("\n%d\n",-1); return ;}int main(){    read(T);    int Case=0;    while(T--){        read(n),read(m),read(t);        int sx,sy;        while(!q.empty()) q.pop();        memset(map,'0',sizeof map );        memset(vis,0,sizeof vis );        for(int i=1;i<=n;++i) scanf("%s",map[i]+1);        for(int i=1;i<=n;++i)            for(int j=1;j<=m;++j)                if(map[i][j]=='S') sx=i,sy=j;        printf("Case %d:",++Case);        solve(sx,sy);    }    return 0;}

4529 郑厂长系列故事——N骑士问题

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 591 Accepted Submission(s): 289
Problem Description
  郑厂长不是正厂长
  也不是副厂长
  他根本就不是厂长
  还是那个腾讯公司的码农
  一个业余时间喜欢下棋的码农
  
  最近,郑厂长对八皇后问题很感兴趣,拿着国际象棋研究了好几天,终于研究透了。兴奋之余,坐在棋盘前的他又开始无聊了。无意间,他看见眼前的棋盘上只摆了八个皇后,感觉空荡荡的,恰好又发现身边还有几个骑士,于是,他想把这些骑士也摆到棋盘上去,当然棋盘上的一个位置只能放一个棋子。因为受八皇后问题的影响,他希望自己把这些骑士摆上去之后,也要满足每2个骑士之间不能相互攻击。
  现在郑厂长想知道共有多少种摆法,你能帮助他吗?
骑士的下法:
  每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走“日”字)。可以越子,没有”中国象棋”的”蹩马腿”限制。
Input
输入第一行为一个整数T(1<=T<=8),表示有T组测试数据;
每组数据首先是一个整数N(1<=n<=10),表示要摆N个骑士上去;
接下来是一个8*8的矩阵来描述一个棋盘,’.’表示这个位置是空的,’*’表示这个位置上已经放了皇后了;
数据中的初始棋盘保证是一个合法的八皇后摆法。
Output
对每组数据,请在一行内输出一个整数,表示合法的方案数。
Sample Input
2
1
*…….
….*…
…….*
…..*..
..*…..
……*.
.*……
…*….
2
*…….
….*…
…….*
…..*..
..*…..
……*.
.*……
…*….
Sample Output
56
1409
Source
2013腾讯编程马拉松初赛第五场(3月25日)

//状压DP#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define MAXN 1<<8int n,dp[2][20][MAXN][MAXN],g[MAXN],cnt[MAXN],mt1[MAXN][MAXN],mt2[MAXN][MAXN];/*状态压缩DP,用dp[i][j][p][q]表示第i-1行状态为p,第i-2行状态为q,前i行放j个骑士时的合法方案数,设前i-1行放j个骑士,第i行放cnt[i]个骑士,则有递推方程dp[i][cnt[i]+j][p][q]+=dp[i-1][j][p][q],初始化dp[i][0][0][0]=1。因为dp数组略大,所以可用滚动数组来降低空间复杂度 */void init(){    for(int i=0;i<MAXN;++i){        for(int j=0;j<8;++j)            if(i&(1<<j)) cnt[i]++;        for(int j=0;j<MAXN;++j){            if(((i>>2)&j)||((j>>2)&i)) mt1[i][j]=1;            //i状态会不会以“横日”走法影响j状态             if(((i>>1)&j)||((j>>1)&i)) mt2[i][j]=1;            //i状态会不会以“竖日”走法影响j状态         }    }}void solve(){    int cur=0;    memset(dp,0,sizeof dp );    dp[0][0][0][0]=1;    for(int i=0;i<8;++i){        cur^=1;        for(int j=0;j<=n;++j)            for(int p=0;p<MAXN;++p)                for(int q=0;q<MAXN;++q){                     if(dp[cur^1][j][p][q]==0) continue;                     for(int z=0;z<MAXN;++z){                         if((z&g[i])!=z) continue;                         if(cnt[z]+j>n) continue;                         if(i>=1&&mt1[q][z]) continue;                         if(i>=2&&mt2[p][z]) continue;                         dp[cur][cnt[z]+j][q][z]+=dp[cur^1][j][p][q];                     }                }        memset(dp[cur^1],0,sizeof dp[cur^1] );    }    int ans=0;    for(int i=0;i<MAXN;++i)        for(int j=0;j<MAXN;++j)            ans+=dp[cur][n][i][j];    printf("%d\n",ans);} int main(){    int t; char temp[10];    init();    scanf("%d",&t);    while(t--){        memset(g,0,sizeof g );        scanf("%d",&n);        for(int i=0;i<8;++i){            scanf("%s",temp);            for(int j=0;j<8;++j){                g[j]<<=1;                if(temp[j]=='.') g[j]|=1;            }        }        solve();    }    return 0;}
阅读全文
0 0
原创粉丝点击