HDU-1107-武林-2014-01-23 20:00:59

武林

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2377    Accepted Submission(s): 637


Problem Description
在一个有12行12列的方形的武林世界里,少林、武当和峨嵋三派的弟子们在为独霸武林而互相厮杀。武林世界的第一行的一列格子的坐标是(1, 1),第一行第二列坐标是(1, 2)……右下角的坐标为(12, 12)。如图:
HDU-1107-武林-2014-01-23 20:00:59_第1张图片
少林派弟子总是在同一列回不停地行走。先往下走,走到头不能再走时就往上走,再到头则又往下走……比如,(1, 1) -> (2, 1) -> (3, 1)。
武当派弟子总是在同一行来回不停地行走。先往右走,走到头不能再走时就往左走,再到头则又往右走……比如,(2, 1) -> (2, 2) -> (2, 3)。
峨嵋派弟子总是在右下-左上方向来回不停走,先往右下方走,走到头不能再走时就往左上方走,再到头则又往右下方走……比如,(1, 1) -> (2, 2) -> (3, 3)。峨嵋弟子如果位于(1,12)或(12,1),那当然只能永远不动。

每次走动,每个弟子必须,而且只能移动一个格子。
每名弟子有内力、武艺、和生命力三种属性。这三种属性的取值范围都是大于等于0,小于等于100。

当有两名不同门派的弟子进入同一个格子时,一定会发生一次战斗,而且也只有在这种情况下,才会发生战斗。(同派弟子之间当然不会自相残杀;一个格子里三派弟子都有时,大家都会因为害怕别人渔翁得利而不敢出手;而多名同门派弟子也不会联手对付敌人,因为这有悖于武林中崇尚的单打独斗精神,会被人耻笑)

一次战斗的结果将可能导致参战双方生命力发生变化,计算方法为:

战后生命力 = 战前生命力 - 对方攻击力

而不同门派的弟子攻击力计算方法不同:

少林派攻击力 = (0.5 * 内力 + 0.5 * 武艺) * (战前生命力 + 10) / 100
武当派攻击力 = (0.8 * 内力 + 0.2 * 武艺) * (战前生命力 + 10) / 100
峨嵋派攻击力 = (0.2 * 内力 + 0.8 * 武艺) * (战前生命力 + 10) / 100

对攻击力的计算过程为浮点运算,最终结果去掉小数点后部分取整,使得攻击力总是整数。
一次战斗结束后,生命力变为小于或等于0的弟子,被视为“战死”,会从武林中消失。
两名不同门派的弟子相遇时,只发生一次战斗。

初始状态下,不存在生命值小于或等于0的弟子,而且一个格子里有可能同时有多个弟子。
一系列战斗从初始状态就可能爆发,全部战斗结束后,仍然活着的弟子才开始一齐走到下一个格子。总之,不停地战斗-行走-战斗-行走……所有弟子都需等战斗结束后,才一齐走到下一个格子。
你需要做的是,从一个初始状态,算出经过N步(N < 1000)后的状态。所有的弟子先进行完全部战斗(当然也可能没有任何战斗发生),然后再一齐走到下一个格子,这称为一步。
所有弟子总数不会超过1000。
 

Input
第一行是测试数据的组数,随后是各组测试数据。
每组数据第一行是行走步数 N。
接下来的若干行,每行描述一名弟子的位置及其各项参数。描述弟子时,格式为“弟子代号 行号 列号 内力 武艺 生命力”。弟子代号就是一个字母:
‘S’ 代表少林派弟子
‘W’ 代表武当派弟子
‘E’ 代表峨嵋派弟子

比如:
W 10 2 10 3 10
表示第10行第2列有一名武当派弟子,他的内力是 10,武艺是3,生命力是10。

每组测试数据以一个结束标志行结尾。结束标志行只含有一个字符’0’。
 

Output
针对每组测试数据,您的输出应该是4行,前3行每行是用空格分隔的两个整数,前一个是某派弟子总数,后一个是本派所有弟子生命力之和。规定第1行代表少林派,第2行代表武当派,第3行代表峨嵋派。第4行是 “***”表示结束。
 

Sample Input
   
   
   
   
2 1 S 1 2 20 20 20 W 2 1 20 20 20 0 2 S 1 2 20 20 20 W 2 1 20 20 20 E 12 12 20 20 100 0
 

Sample Output
   
   
   
   
1 20 1 20 0 0 *** 1 14 1 14 1 100 ***
 

Source
POJ
 

一次见到这么麻烦的模拟题。题意不是很难理解,但是做起来相当麻烦。用结构体和小函数写会比较清晰一点。写了一整天, 水平还是渣啊~


# include<stdio.h>
# include<string.h>
typedef struct dizi
{
    char menpai;  //弟子门派
    int row;    //所在行数
    int column;    //所在列数
    int neili;    //内力
    int wuyi;    //武艺
    int shengming;    //生命
    int gongjili;    //攻击力
    int flag;        //是否死亡 1活着 0死亡
    int isf;        //是否格斗过 1斗过 0木有        
    int fangxiang;    //走向 正为0 反为1
}a[1010];
int map[14][14];    //整个武林

int gjl(char menpai,int neili,int wuyi,int shengming)    //计算各位弟子的攻击力
{
    double a = 1.0;
    if(menpai=='S')
    {
        return (int)(a*(0.5*neili+0.5*wuyi)*(shengming+10)/100);
    }
    else if(menpai=='W')
    {
        return (int)(a*(0.8*neili+0.2*wuyi)*(shengming+10)/100);    
    }
    else
    {
        return (int)(a*(0.2*neili+0.8*wuyi)*(shengming+10)/100);
    }
} 

int jieguo(int shengming,int dgjl)    //一次不同帮派拼杀后剩余血量
{
    return shengming-dgjl;
}

void zhandou(int map[][14],dizi a[],int k1)        //开始拼杀了
{    
    int i,j,k,b1,b2;
    for(i=1;i<=12;i++)
    {
        for(j=1;j<=12;j++)
        {
            if(map[i][j]==2)    //当武林的同一个位置有两个人时
            {
                for(k=0;k<k1;k++)    //找到这个位置上 没死~没战斗过的第一位弟子
                {
                    if(a[k].row==i && a[k].column==j && a[k].flag!=0 && !a[k].isf)  
                    {
                        b1 = k;
                        k++;
                        break;
                    }
                }    
                for(;k<k1;k++)    //找到这个位置上 没死~没战斗过的第一位弟子
                {
                    if(a[k].row==i && a[k].column==j && a[k].flag!=0 && !a[k].isf)
                    {
                        b2 = k;
                        break;
                    }
                }
                if(a[b1].menpai!=a[b2].menpai && a[b1].flag!=0 && !a[b1].isf && a[b2].flag!=0 && !a[b2].isf)  //仇人见面~开始拼杀
                {
                    a[b1].shengming=jieguo(a[b1].shengming,a[b2].gongjili);        //第一个人战斗后的生命值
                    a[b2].shengming=jieguo(a[b2].shengming,a[b1].gongjili);        //第二个人战斗后的生命值
                    a[b1].gongjili = gjl(a[b1].menpai,a[b1].neili,a[b1].wuyi,a[b1].shengming);
                    a[b2].gongjili = gjl(a[b2].menpai,a[b2].neili,a[b2].wuyi,a[b2].shengming);
                    if(a[b1].shengming<=0)        //第一个死了~
                    {
                        a[b1].shengming = 0;
                        a[b1].flag = 0;
                    } 
                    if(a[b2].shengming<=0)        //第二个死了~
                    {
                        a[b2].shengming = 0;
                        a[b2].flag = 0;    
                    }
                    a[b1].isf = 1;        //本回合已拼斗过
                    a[b2].isf = 1;        //本回合已拼斗过
                }
            }
        }
    }
}

void yidong(int map[][14],dizi a[],int k1)
{
    int k; 
    zhandou(map,a,k1);//这里是map,而不是map[14][14] map是地址 map[14][14]是 int型 
    memset(map,0,sizeof(map)*14*14);
    for(k=0;k<k1;k++)
    {
        a[k].isf = 0;
        if(a[k].menpai=='S' && a[k].flag!=0)        //少林派步法
        {
            if(a[k].fangxiang==0)
            {
                if(a[k].row+1<=12)            //下移
                    a[k].row++;            
                else                        //到头了,上移
                {
                    a[k].row--;
                    a[k].fangxiang = 1;
                }
            }
            else if(a[k].fangxiang==1)        
            {
                if(a[k].row-1>=1)            //上移
                    a[k].row--;
                else                        //到头了,下移
                {
                    a[k].row++;
                    a[k].fangxiang = 0;
                }
            }
            map[a[k].row][a[k].column]++;    //移动后,新位置人数加一
        }
        else if(a[k].menpai=='W' && a[k].flag!=0)        //武当派步法
        {
            if(a[k].fangxiang==0)            
            {
                if(a[k].column+1<=12)        //右移
                    a[k].column++;
                else                        //到头了,左移
                {
                    a[k].column--;
                    a[k].fangxiang = 1;
                }
            }
            else if(a[k].fangxiang==1)        
            {
                if(a[k].column-1>=1)        //左移
                    a[k].column--;
                else                        //到头了,右移
                {
                    a[k].column++;
                    a[k].fangxiang = 0;
                }
            }
            map[a[k].row][a[k].column]++;    //移动后,新位置人数加一
        }
        else if(a[k].menpai=='E' && a[k].flag!=0)        //峨眉派飘逸步法
        {
            if(a[k].fangxiang==0)
            {
                if(a[k].row+1<=12 && a[k].column+1<=12 && (a[k].row!=1 || a[k].column!=12) && (a[k].row!=12||a[k].column!=1))    //右下移,位置不为1,12 12,1
                {
                    a[k].row++;
                    a[k].column++;
                }
                else if(a[k].row+1>12 || a[k].column+1>12 && (a[k].row!=1 || a[k].column!=12) && (a[k].row!=12||a[k].column!=1))        //到头了,左上移
                {
                    a[k].row--;
                    a[k].column--;
                    a[k].fangxiang = 1;
                }
                map[a[k].row][a[k].column]++;        //移动后,新位置人数加一
            }
            else if(a[k].fangxiang==1)
            {
                if(a[k].row-1>=1 && a[k].column-1>=1 && (a[k].row!=1 || a[k].column!=12) &&(a[k].row!=12||a[k].column!=1))        //左上移,位置不为1,12 12,1
                {
                    a[k].row--;
                    a[k].column--;
                }    
                else if(a[k].row-1<1 || a[k].column-1<1 && (a[k].row!=1 || a[k].column!=12) &&(a[k].row!=12||a[k].column!=1))        //到头了,右下移
                {
                    a[k].row++;
                    a[k].column++;
                    a[k].fangxiang = 0;
                }
                map[a[k].row][a[k].column]++;        //移动后,新位置人数加一
            }
        }

    }
}

int main() 
{
    int M,N,i,j,k,l,neili,wuyi,shengming,SSUM,WSUM,ESUM,ssum,wsum,esum;
    char ch;
    dizi a[1010];
    scanf("%d",&M);
    while(M--)
    {
        getchar();
        memset(map,0,sizeof(map));
        k = 0;
        scanf("%d",&N);
        getchar();
        while(scanf("%c",&ch) && ch!='0')
        {
            if(ch=='\n')
                continue;
            scanf("%d",&i);
            scanf("%d",&j);
            scanf("%d",&neili);
            scanf("%d",&wuyi);
            scanf("%d",&shengming);
            if(ch == 'S' || ch == 'W' || ch =='E')
                a[k].menpai = ch;
            a[k].row = i;
            a[k].column = j;
            a[k].neili = neili;
            a[k].wuyi = wuyi;
            a[k].shengming = shengming;
            a[k].gongjili = gjl(ch,neili,wuyi,shengming);
            a[k].flag = 1;
            a[k].fangxiang = 0;
            a[k].isf = 0;
            map[i][j]++;
            k++;
        }
        while(N--)
        {
            yidong(map,a,k);
        }
        SSUM =WSUM = ESUM = ssum = wsum = esum = 0;
        
        for(l=0;l<k;l++)
        {
            if(a[l].menpai=='S' && a[l].flag!=0)
            {
                ssum += a[l].shengming;
                SSUM++;
            }    
            if(a[l].menpai=='W' && a[l].flag!=0)
            {    
                wsum += a[l].shengming;
                WSUM++;
            } 
            if(a[l].menpai=='E' && a[l].flag!=0)
            {
                esum += a[l].shengming;
                ESUM++;
            } 
        }
        printf("%d %d\n",SSUM,ssum);
        printf("%d %d\n",WSUM,wsum);
        printf("%d %d\n",ESUM,esum);
        printf("***\n");
    }
    return 0;
}


你可能感兴趣的:(HDU-1107-武林-2014-01-23 20:00:59)