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

53 篇文章 1 订阅
26 篇文章 0 订阅

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 0x3f3f3f3f
const 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 105
char 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<<8
int 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值