uvalive5810 uva12368 Candles

题意:每组数据给出n个数,每个数在1-100,问组成这些数的蜡烛的权值的最小值。权值=把选的蜡烛从大到小排列组成的数

组成方式:比如有1 3两个蜡烛 可以组成13(1和3)或4(1+3) 只有一个加号可以用

解:位运算记录状态,can[i][j]表示在i的二进制所记录的状态下能不能组成j

can直接预处理出来,分类讨论 用一个数表示 还是用两个数表示 check的时候都在100以内 直接枚举

 1 #include<cstdio>

 2 #include<cmath>

 3 #include<algorithm>

 4 #include<cstring>

 5 

 6 using namespace std;

 7 

 8 int n;

 9 bool can[1024][101];

10 int a[11];

11 int cas=0;

12 

13 bool check1(int x,int y,int z){

14     int cnt[11];

15     memset(cnt,0,sizeof(cnt));

16     int tmp=y;

17     while (tmp!=0){

18             int now=tmp%10;

19             tmp=tmp/10;

20             if (((x&(1<<now))==0)||(cnt[now]>0)) return false;

21             cnt[now]++;

22     }

23     tmp=z;

24     while (tmp!=0){

25             int now=tmp%10;

26             tmp=tmp/10;

27             if (((x&(1<<now))==0)||(cnt[now]>0)) return false;

28             cnt[now]++;

29     }

30     return true;

31 }

32 

33 bool check(int x,int y){

34     if ((y<10)&&(x&(1<<y))) return true;

35     for (int i=1;i<=y/2;i++){

36             if (i!=(y-i)){

37                     if (check1(x,i,y-i)) return true;

38             }

39     }

40     if (y==100) return false;

41     int tmpy1=y/10;

42     int tmpy2=y%10;

43     if (tmpy1==tmpy2) return false;

44     if ((x&(1<<tmpy1))==0) return false;

45     if ((x&(1<<tmpy2))==0) return false;

46     return true;

47 }

48 

49 int main(){

50     memset(can,0,sizeof(can));

51     for (int i=1;i<1024;i++){

52             for (int j=1;j<=100;j++) can[i][j]=check(i,j);

53     }

54     while (1){

55             scanf("%d",&n);

56             if (n==0) return 0;

57             cas++;

58             bool flag;

59             int ans=0;

60             for (int i=1;i<=n;i++) scanf("%d",&a[i]);

61             for (int i=1;i<1024;i++){

62                     flag=true;

63                     for (int j=1;j<=n;j++) if (!can[i][a[j]]) flag=false;

64                     if (flag){

65                             int tmp=0;

66                             for (int j=9;j>=0;j--) if (i&(1<<j)) tmp=tmp*10+j;

67                             if ((ans==0)||(ans>tmp)) ans=tmp;

68                     }

69             }

70             printf("Case %d: %d\n",cas,ans);

71     }

72     return 0;

73 }

74 /*

75 2 10 11

76 1 30

77 0

78 */

79   

 

你可能感兴趣的:(live)