1067

据点轰炸


A国要对B国的展开军事行动,计划摧毁B国领土上的所有军事据点。已知B国国土呈长条状,划分为若干个区域,如图所示:
这里写图片描述

军事据点有N个,分布在N个不同的区域内。A国的轰炸机投放的炸弹有一定的攻击范围,每个炸弹的爆炸范围可以覆盖K个区域的大小。为了减少战后重建的费用,A国希望在保证摧毁所有军事据点的同时,受炸弹波及的区域尽可能少。给定B国军事据点的位置和任意数量的炸弹,要求摧毁所有B国军事据点的同时,求出受波及区域的最少数量。

例如,军事据点位置分别在5,8,19,21,炸弹轰炸的范围K=3,那么按照图示的轰炸方法分3次轰炸可以摧毁所有据点同时保证被波及的波及区域数量最少,最小值为7:
这里写图片描述

Input

  • 第一行为整数T。

  • 接下来T组用例,每组两行,第一行给定N,K,第二行给定N个整数Ai,表示军事据点编号。

  • 其中4<=N<=100,1<=K<=10000,0<=Ai<=10000

Output
分别输出每一个用例的最少受波及区域数量。
Sample Input

5
4 3
5 21 8 19
8 3
22 9 19 6 20 5 7 2
10 2
0 10 2 12 4 14 6 16 8 18
40 15
402 444 322 123 302 183 380 80 200 533 299 147 189 528 268 181 404 270 432 236 525 316 487 412 241 33 414 357 542 489 466 174 226 69 308 565 317 539 170 455 
100 13
3242 3191 1819 1458 2193 1090 4759 1598 2255 4539 331 727 2954 4620 3499 4735 2044 259 3753 4003 1308 3054 53 3980 20 2715 4663 2241 1613 112 1248 4249 413 3382 4398 212 1430 2054 4683 2856 4326 4878 1163 3265 1287 77 3880 3729 855 566 4376 4271 4484 4140 951 3359 891 3647 2490 1352 4416 2825 4858 4712 3738 1510 2524 4814 3866 1261 466 4692 3154 3558 874 2622 1666 4897 2123 1529 3290 716 1701 1059 4746 592 4224 3766 2367 2643 2779 3581 4028 2540 1944 3695 577 828 2267 4128

Sample Output

#1 7
#2 12
#3 15
#4 257
#5 1094

code

#include <stdio.h>
#define MAX 101
int map[MAX] = {0};
int dp[MAX][MAX] = {0};
int N,K;

int fun(int start, int ending)
{
    int temp_N = ending-start+1;
    for (int i = 1; i < temp_N; i++)
    {
        for (int j = start; j + i <= ending; j++)
            if (map[j] + K > map[j + i]) dp[j][j + i] = K;
            else
            {
                dp[j][j + i] = map[j + i] - map[j] + 1;
                for (int v = j; v < j + i; v++)
                    if (dp[j][j + i] > dp[j][v] + dp[v + 1][j + i])
                        dp[j][j + i] = dp[j][v] + dp[v + 1][j + i];
            }
    }
    return dp[start][ending];
}

int main()
{
    int T;
    //freopen("input.txt", "r", stdin);
    scanf("%d", &T);
    for (int test_case=1;test_case<=T;test_case++)
    {
        scanf("%d %d", &N, &K);
        for (int i=0;i<N;i++)
        {
            scanf("%d", &map[i]);
            dp[i][i] = K;
        }

        int temp;
        for (int i=0;i<N-1;i++)
        {
            for (int j=i+1;j<N;j++)
                if (map[i]>map[j])
                {
                    temp = map[i];
                    map[i] = map[j];
                    map[j] = temp;
                }
        }

        int start,ending,index;
        start=index=0;ending=N-1;
        int result = 0;
        while(start<ending)
        {
            if (map[start+1]-map[start]<2*K-1)
            {
                start++;
                continue;
            }
            result += fun(index, start);
            start++;
            index = start;
        }
        result += fun(index, start);
        printf("#%d %d\n", test_case, result);
    }
    return 0;
}
#include<stdio.h>
#include<iostream>
#define DEBUG_IO 0
const int SIZE = 10001;
int a[SIZE];
void quick_sort(int left, int right, int a[]);
void output_b(int N, int b[]);
int main()
{
    int i,j,k;
    int ans;
    int T;
    scanf("%d", &T);

    int N,K;

    for(int t = 1; t <= T; t++)
    {
        int b[SIZE] = {0};
        //input data
        scanf("%d %d", &N, &K);
        for(i = 0; i < N; i++)
        {
            scanf("%d", &a[i]);
            b[a[i]] = 2;
        }


        ans = 0;

        quick_sort(0, N - 1, a);

#if DEBUG_IO
        for(i = 0; i < N; i++)
        {
            printf("%d ", a[i]);
        }
        printf("\n");
        output_b(N, b);
#endif

        //初始化第一个据点的K区间
        for(int i = a[0]; i < a[0] + K; i++)
        {
            b[i] = 1;
        }

        for(int k = 1; k < N; k++)
        {
            int temp = K;
            int start = a[k] - K +1;
            int end = a[k] + K - 1;
            int index = start;
            for( i = start; i <= end; i++)//这个据点2K范围内
            {
                int count = 0;
                for( j = i; j < i + K; j++)
                {
                    if(b[j] == 0)
                    {
                        count++;
                    }
                    else
                    {
                        b[j] = 1;
                    }
                }
                if(temp >= count)
                {
                    temp = count;
                    index = i;
                }
            }

            for(i = index; i < index + K; i++)
            {
                b[i] = 1;
            }
            output_b(N, b);
        }

        for(i = a[0]; i <= a[N-1]; i++)
        {
            ans+=b[i];
        }

        printf("#%d %d\n", t, ans);
    }
    return 0;
}
void output_b(int N, int b[])
{
#if DEBUG_IO
    for(int i = a[0]; i <= a[N-1]; i++)
    {
        printf("%d ", b[i]);
    }
    printf("\n");
#endif
}
void quick_sort(int left, int right, int a[])
{
    if(left < right)
    {
        int l = left;
        int r = right;
        int temp = a[l];
        while(l < r)
        {
            while(l < r && a[r] > temp)
            {
                r--;
            }
            if(l < r)
            {
                a[l++] = a[r];  
            }

            while(l < r && a[l] < temp)
            {
                l++;
            }
            if(l < r)
            {
                a[r--] = a[l];
            }
        }
        a[l] = temp;
        quick_sort(left, l-1, a);
        quick_sort(l+1, right,a);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值