算法竞赛入门经典(第2版)习题4-10 洪水! Flooded! UVa815

这篇博客介绍了如何解决算法竞赛入门经典(第2版)中的习题4-10——UVa815洪水问题。作者提出了两种不同的解题思路,包括对所有格子按海拔排序,然后分别通过不同方法计算含水量。解法一是通过累加计算,解法二是逐个计算含水海拔并比较高度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此题作者建议使用多种方法解题锻炼一下

我想到了若干解法,基本大同小异,真正核心的计算海拔的算法只想出两种:

第一个解法:把所有格子按海拔顺序排序,把每一档海拔与下一档之间能够容纳的水依次累加直到大于水的总体积。

第二个解法:把所有格子按海拔顺序排序,逐个计算含水海拔,第n个格子的含水海拔=(总水量+n个格子相对于0海拔的体积)/n个格子的面积和,顺序读入后面格子海拔,如果此格高于已算出的含水海拔则终止。

解法一:

//#define LOCAL
//#define TESTING
#include<stdio.h>
#include<string.h>

void swap(int* a, int* b)//变量值交换函数
{
    int t = *a; *a = *b; *b = t;
}

int main()
{
    #ifdef LOCAL
    freopen("xt4-10.in","r",stdin);
    #endif
    int m,n,kase=0;
    while(scanf("%d%d",&m,&n)==2&&m&&n)
    {
        kase++;
        #ifdef TESTING
        printf("%d %d\n", m, n);
        #endif
        int tot = m*n;//tot格子总数
        int grid[tot+2],water;//grid[]格子海拔 water水量
        for(int i = 1; i <= tot; i++)//读入格子海拔并顺序排序
        {
            scanf("%d",&grid[i]);
            for(int j = i; j > 1; j--)
            {
                if(grid[j]<grid[j-1]) swap(&grid[j-1],&grid[j]);
                else break;
            }
        } 
        scanf("%d",&water);//读入水量
        #ifdef TESTING
        for(int i = 1; i <= tot; i++) printf("%d ",grid[i]);
        printf("\n%d\n",water);
        #endif
        int amt=0,gridamt = 0,totvol = 0;//amt被水淹没的格子数量 gridamt 纳入容积计算的格子数量 totvol纳入计算的容积总量
        float wlevel;//wlevel最终海拔
        for(int i = 1; i <= tot; i++)//从海拔最低的格子开始计算
        {
            gridamt=i-1;//被水淹没的格子数量
            int tempvol = 0;//本轮计算的容积
            int addgrid=1;//同档海拔的纳入海拔计算的格子数量
            for(int j = i+1; j <= tot+1; j++)//统计本轮计算同档海拔格子数量,统计完成后计算本轮新增容积
            {
                if(j==(tot+1))//如果本轮所有格子都已纳入计算
                {
                    gridamt = tot;
                    tempvol = water;
                    i=tot;
                }
                else if(grid[j] == grid [i]) addgrid++;//如果海拔与本轮第一个格子相等则addgrid+1
                else//如果不等则计算海拔
                {
                    gridamt+=addgrid;//将本轮增加的格子数纳入被水淹没的格子总量
                    tempvol = (grid[j] - grid[i])*gridamt*100;//计算本轮新增容积
                    #ifdef TESTING
                    printf("\n%d %d %d %d %d %d\n",i,grid[i],grid[j],gridamt,tempvol,totvol);
                    #endif
                    i=j-1;
                    break;//完成计算后跳出循环
                }
            }
            amt = i;
            if(totvol+tempvol>=water)//如果本轮总容积大于等于水量或所有格子均纳入计算
            {
                wlevel = grid[gridamt]+(water - totvol)/(gridamt*100.0);//计算最终海拔
                #ifdef TESTING
                printf("\n%d %d %d %d\n",grid[i-addgrid],water,totvol,gridamt);
                #endif
                break;
            }
            else totvol += tempvol;//如果本轮总容积小于水量且还有未纳入计算的格子,更新已计算总容积
        }
        #ifdef TESTING
        
        #endif
        printf("Region %d\nWater level is %.2lf meters.\n",kase,wlevel);//输出案例序号,最终海拔
        printf("%.2lf percent of the region is under water.\n\n",amt*100.0/tot);//输出有水区域所占百分比
    }
    return 0;
}


解法二:

#include<string.h>
#include<stdio.h>

void swap(int* a, int* b)
{
    int t= *a; *a = *b; *b = t;
}

int main()
{
    int m,n,kase = 0;
    while(scanf("%d%d",&m,&n)==2&&m&&n)
    {
        kase++;
        int grid[m*n+1],stat[m*n+1],tot = m*n,water;
        int amt=0;
        float wlevel,totvol=0.0;
        for(int i = 1; i <= tot; i++)
        {
            scanf("%d", &grid[i]);
            for(int j = i; j >1; j--)
            {
                if(grid[j]<grid[j-1]) swap(&grid[j],&grid[j-1]);
                else break;
            }
        }
        scanf("%d", &water);
        for(int i = 1; i <= tot; i++)
        {
            if(i==1)
            {
                amt++;
                totvol = grid[1]*100.0;
                wlevel = (water+totvol)*1.0/(100*amt);
            }
            else if(grid[i]<wlevel)
            {
                amt++;
                totvol += grid[i]*100.0;
                wlevel = (water + totvol)*1.0/(100*amt);
            }
            else break;
        }
        printf("Region %d\nWater level is %.2lf meters.\n", kase,wlevel);
        printf("%.2lf percent of the region is under water.\n\n", amt*100.0/tot);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值