24/7每日一题acm

介绍
你长期以来一直是一个寻宝者。你很擅长解除陷阱,偷偷溜过当地人,通常在你的皮肤完好无损的情况下得到货物。这件事并不是真的让你担心,但真正让人大吃一惊的是每次探险结束后,总会有关于如何分赃的激烈争论。你和各种各样的人物一起工作,没有人同意每一件珍宝的价值。你需要想出一种尽可能公平地分割战利品的方法。

输入
对这个问题的输入将包括一个(非空)系列多达100个数据集。每个数据集将根据下面的描述进行格式化,并且不会有分隔数据集的空白行。
单个数据集有5个组成部分:
起始线-单线“START”
珍宝的数量-一个单一的整数与一个整数t,其中1 <=T<8,表示宝藏的数量。
猎人数量-一条带有一个整数的单线h,其中1 <= h <=6,表示寻宝者的数量。
珍宝价值列表-一系列的H线,每个猎人一个序列(猎人1线1,猎人2线2,等等)。每一行包含一个空间分隔的列表,估计该猎人的财富值。每一行的第一个估计值是宝藏1,第二个是宝藏2,等等,每个猎物的估计都会出现在每个猎人身上。每个估计将是严格小于10000的正整数。
结束线-单行,“END”

产量
对于每个输入数据集,将有一个精确的输出集,并且正好有一条空白线分离输出集。
每个输出集由多条线组成,其中每一条线代表一个猎人(以与相应的输入数据集相同的顺序列出)。每一行都有一份清单,列出了猎人的财宝,以及他们所收到的所有财宝的总现金价值。珍宝将按宝座编号升序排列,每条线上的所有值将是空间分隔的。
珍宝将以最公平的方式分给猎人们。划分财富的“最公平”方式是指在任何一个狩猎者收到的珍宝中,最高感知总价值和最低感知总价值之间的最小差异。换言之,找到最大限度地减少猎人获得“最”和最小的猎人之间的差异的分布。
不会有多个“公平”分布。

样本输入:

START
5
3
42 500 350 700 100
250 200 500 1000 75
150 400 800 800 150
END
START
5
3
42 500 350 200 100
250 200 500 1000 75
150 400 800 800 150
END
START
5
3
500 500 350 200 100
250 200 500 1000 75
150 400 800 800 150
END

样本输出:

4 700
3 5 575
1 2 550

1 4 5 342
3 500
2 400

1 2 1000
4 1000
3 5 950

 

 

代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
 
const int Max = 0x7fffffff;
struct Node{
    int val[ 10 ];
}a[ 10 ];
struct Node2{
    int num[ 10 ];
    int cnt ,sum ;
}ans[ 10 ],dfs_ans[ 10 ];
int vis[ 10 ];
int diff;
bool flag[ 10 ];
 
void init(){
    diff = Max;
    memset( flag,false,sizeof( flag ) );
    for( int i=0;i<10;i++ ){
        for( int j=0;j<10;j++ ){
            ans[ i ].num[ j ] = dfs_ans[ i ].num[ j ] = 0;
        }
        ans[ i ].cnt = ans[ i ].sum = dfs_ans[ i ].cnt = dfs_ans[ i ].sum = 0;
    }
}
 
void init_vis( int n ){
    int N = (1<<n);
    for( int i=0;i<N;i++ ){
        for( int j=0;j<n;j++ ){
            if( i&(1<<j) ) vis[ j ] = 0;
            else vis[ j ] = 1;
        }
    }
}
 
void dfs( int cur_hunter,int cur_treasure,int num_treasure,int hunter ){
    if( cur_hunter==hunter&&cur_treasure==num_treasure ){
        int t_max = dfs_ans[0].sum;
        int t_min = dfs_ans[0].sum;
        for( int i=1;i<hunter;i++ ){
            t_max = max( t_max,dfs_ans[i].sum );
            t_min = min( t_min,dfs_ans[i].sum );
        }
        if( t_max-t_min<diff ){
            diff = t_max-t_min;
            for( int i=0;i<hunter;i++ )
                ans[i] = dfs_ans[i];
        }
        return ;
    }
    if( cur_hunter>=hunter ) return ;
    int N = (1<<num_treasure);
    for( int i=0;i<N;i++ ){
        int t_cnt = 0;
        bool p_flag = true;
        for( int j=0;j<num_treasure;j++ ){
            if( i&(1<<j) ) vis[ j ] = 0;
            else {
                vis[ j ] = 1;
                t_cnt++;
                if( flag[j]==true ) {
                    p_flag = false;
                    break;
                }
            }
        }
        if( p_flag==true&&( t_cnt+cur_treasure+hunter-cur_hunter-1 )<=num_treasure ){
            int tt = 0;
            dfs_ans[ cur_hunter ].sum = 0;
            dfs_ans[ cur_hunter ].cnt = t_cnt;
            for( int j=0;j<num_treasure;j++ ){
                if( vis[j] == 1 ){
                    dfs_ans[ cur_hunter ].num[ tt++ ] = j;
                    flag[ j ] = true;
                    dfs_ans[ cur_hunter ].sum += a[ cur_hunter ].val[j];
                }
            }
            dfs( cur_hunter+1,cur_treasure+t_cnt,num_treasure,hunter);
            for( int j=0;j<tt;j++ ){
                flag[ dfs_ans[ cur_hunter ].num[j] ] = false;
            }
        }
    }
    return ;
}
 
int main(){
    int num_treasure,hunter;
    char s[ 12 ];
    int ca = 1;
    while( scanf("%s",s)!=EOF ){
        init();
        scanf("%d%d",&num_treasure,&hunter);
        for( int i=0;i<hunter;i++ ){
            for( int j=0;j<num_treasure;j++ ){
                scanf("%d",&a[i].val[j]);
            }
        }
        scanf("%s",s);
        if( num_treasure==1 ){
            int m_min = a[0].val[0];
            int m_num = 0;
            for( int i=1;i<hunter;i++ ){
                if( m_min>a[i].val[0] ){
                    m_min = a[ i ].val[0];
                    m_num = i;
                }
            }
            if( ca!=1 ) printf("\n");
            ca++;
            for( int i=0;i<hunter;i++ ){
                if( i==m_num ){
                    printf("1 %d\n",m_min);
                }
                else
                    printf("0\n");
            }
            continue;
        }
        dfs( 0,0,num_treasure,hunter );
        if( ca!=1 ) printf("\n");
        ca++;
        for( int i=0;i<hunter;i++ ){
            for( int j=0;j<ans[i].cnt;j++ ){
                if( j==0 )
                    printf("%d",ans[i].num[j]+1);
                else
                    printf(" %d",ans[i].num[j]+1);
            }
            if( ans[i].cnt>0 ) printf(" %d\n",ans[i].sum);
            else printf("%d\n",ans[i].sum);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值