bjfuOJ 1017组合的字典序(模拟求直接后继,分情况讨论)


组合的字典序

时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte
总提交:51            测试通过:28

描述

一个组合问题可以抽象为从n-1个整数0、1、2 ... (n-1)中选取m个。选中的m个数构成序列,并且从小到大排列,称为生成序列。不同的生成序列按照字典序有先后顺序。一个生成序列的直接后继是另外一个生成序列:这个序列与其直接后继之间没有其他任何生成序列。最后一个生成序列之后的生成序列不存在,但可以人为地规定为每个元素的值都是-1。

输入

第一行是一个整数k,表示测试用例的多少。每个测试用例的输入是若干独立的行。
对每一个测试用例,其第一行是两个整数ni和mi(用单个空格隔开),第一个整数ni(ni在区间[2,30]中),表示了被选序列的大小;第二个整数mi(mi在区间[1, ni]中),表示被选出序列的大小。后面的mi行表示被选出的序列,每一行分别是一个正整数,在[0, ni-1]之中,并且递增排列。

输出

对每一个mi长度的输入序列,用mi行输出其直接后继(长度仍然是mi)。

样例输入

3
10 4
0
2
8
9
3 2
1
2
5 2
2
4

样例输出

0
3
4
5
-1
-1
3
4


·第二遍打这个题了,,比第一遍相对来说顺手的多

分情况讨论并作处理,迭代开发,对于这类模拟题,感觉真的屡试不爽。。。


#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <queue>
#include <stack>
using namespace std;
#define N 10100
#define INF 1<<27
#define LL long long

//先已经没有后继的; 有,则计算
int f[N];
int check(int n,int m){
    int flag=1;n--;
    for(int i=m-1;i>=0;i--){
        if(f[i]==n){
            n--;
        }else{
            flag=0;break;
        }
    }
    return flag;
}
void deal(int n,int m){
    int flag=0;
    for(int i=0;i<m;i++)
        if(f[i]==(n-1)){
            flag=i;break;  //含最大的数字! 处理比较麻烦
        }
    if(!flag){
        //简单+1处理
        for(int i=0;i<m-1;i++)
            printf("%d\n",f[i]);
        printf("%d\n",f[m-1]+1);
    }else{
        n-=2;int i;
        for(i=flag-1;i>=0;i--){
            if(f[i]==n){
                n--;continue;
            }else{
                flag=i;break;
            }
        }
        if(i==-1){
            //没有后继
            for(int i=0;i<m;i++)
                printf("-1\n");
        }
        else{
            //有后继
            for(int i=0;i<flag;i++){
                printf("%d\n",f[i]);
            }
            int t = f[flag]+1;
            for(int i=flag;i<m;i++){
                printf("%d\n",t);t++;
            }
        }
    }
}
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i=0;i<m;i++)
            scanf("%d",&f[i]);
        if(check(n,m)){
            for(int i=0;i<m;i++)
                printf("-1\n");
            continue;
        }
        //否则,计算直接后继并输出
        deal(n,m);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,我无法找到关于分糖果字典的Java代码。但是,我可以为您提供一个解决这个问题的思路。 您可以使用递归的方式来解决这个问题。首先,创建一个函数来模拟每一轮分糖果的过程。然后,使用一个循环来遍历每个小朋友,将其糖果数量减半并分给左手边的孩子。如果分完后有奇数颗糖果,就补充1颗糖果使其变成偶数。接着,判断是否所有小朋友的糖果数量都相同,如果是,则返回当前轮次的糖果补充数量;如果不是,则递归调用函数进行下一轮分糖果。 以下是一个可能的Java实现: ```java import java.util.Arrays; public class CandyDistribution { public static int distributeCandies(int[] candies) { int n = candies.length; int sum = Arrays.stream(candies).sum(); int avg = sum / n; int count = 0; if (sum % n != 0) { return -1; // 无法平均分配糖果 } while (!isAllEqual(candies)) { for (int i = 0; i < n; i++) { int left = (i == 0) ? n - 1 : i - 1; int right = (i == n - 1) ? 0 : i + 1; if (candies[i] % 2 != 0) { candies[i]++; count++; } int give = candies[i] / 2; candies[i] -= give; candies[left] += give; candies[right] += give; } } return count; } private static boolean isAllEqual(int[] arr) { for (int i = 1; i < arr.length; i++) { if (arr[i] != arr[0]) { return false; } } return true; } public static void main(String[] args) { int[] candies = {2, 4, 6, 8}; int result = distributeCandies(candies); System.out.println("Total candies needed: " + result); } } ``` 请注意,这只是一个可能的解决方案,具体实现可能因问题的具体要而有所不同。您可以根据自己的需进行修改和调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值