您的位置:首页 > 其它

uvalive5810 uva12368 Candles

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

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

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

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

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>

using namespace std;

int n;
bool can[1024][101];
int a[11];
int cas=0;

bool check1(int x,int y,int z){
int cnt[11];
memset(cnt,0,sizeof(cnt));
int tmp=y;
while (tmp!=0){
int now=tmp%10;
tmp=tmp/10;
if (((x&(1<<now))==0)||(cnt[now]>0)) return false;
cnt[now]++;
}
tmp=z;
while (tmp!=0){
int now=tmp%10;
tmp=tmp/10;
if (((x&(1<<now))==0)||(cnt[now]>0)) return false;
cnt[now]++;
}
return true;
}

bool check(int x,int y){
if ((y<10)&&(x&(1<<y))) return true;
for (int i=1;i<=y/2;i++){
if (i!=(y-i)){
if (check1(x,i,y-i)) return true;
}
}
if (y==100) return false;
int tmpy1=y/10;
int tmpy2=y%10;
if (tmpy1==tmpy2) return false;
if ((x&(1<<tmpy1))==0) return false;
if ((x&(1<<tmpy2))==0) return false;
return true;
}

int main(){
memset(can,0,sizeof(can));
for (int i=1;i<1024;i++){
for (int j=1;j<=100;j++) can[i][j]=check(i,j);
}
while (1){
scanf("%d",&n);
if (n==0) return 0;
cas++;
bool flag;
int ans=0;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<1024;i++){
flag=true;
for (int j=1;j<=n;j++) if (!can[i][a[j]]) flag=false;
if (flag){
int tmp=0;
for (int j=9;j>=0;j--) if (i&(1<<j)) tmp=tmp*10+j;
if ((ans==0)||(ans>tmp)) ans=tmp;
}
}
printf("Case %d: %d\n",cas,ans);
}
return 0;
}
/*
2 10 11
1 30
0
*/
  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: