2015_6

C - Cards UVA 12369

好题,有一副顺序随机的扑克牌,一张张翻开,问至少c,d,h,s张黑桃红心草花方片的期望要翻开的张数。其中两张鬼牌可以代替任意一种花色,当翻到鬼牌时,鬼牌要选择变成一种花色使得期望值最小,并且选完之后这张鬼牌就不能再变化了。两张鬼牌都一样且互不影响。

深搜记忆化dp,dp[a][b][c][d][e][f]存 从 a张黑桃 b张红心 c张草花 d张方片ef状态到符合题意的要求还需要翻的次数 的期望值, e 表示大鬼状态,f表示小鬼状态,e和f 为0表示未翻开,e和f==1,2,3,4,分别表示这张鬼变成某种颜色。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int M=16;
 5 double dp[M][M][M][M][8][8];
 6 int s[8];
 7 double dfs(int a,int b,int c,int d,int e,int f){
 8     double& tmp=dp[a][b][c][d][e][f];
 9     if(tmp!=-1) return tmp;
10     if(a+(e==1)+(f==1)>=s[0]&&b+(e==2)+(f==2)>=s[1]&&c+(e==3)+(f==3)>=s[2]&&d+(e==4)+(f==4)>=s[3]){
11         tmp=0;
12         return tmp;
13     }
14     int tot=0;
15     tot+=13-a;
16     tot+=13-b;
17     tot+=13-c;
18     tot+=13-d;
19     tot+=(e==0);
20     tot+=(f==0);
21     double ans=1;
22     if(a<13){
23         ans+=(13.0-a)/tot*dfs(a+1,b,c,d,e,f);
24     }
25     if(b<13){
26         ans+=(13.0-b)/tot*dfs(a,b+1,c,d,e,f);
27     }
28     if(c<13){
29         ans+=(13.0-c)/tot*dfs(a,b,c+1,d,e,f);
30     }
31     if(d<13){
32         ans+=(13.0-d)/tot*dfs(a,b,c,d+1,e,f);
33     }
34     if(!e){
35         double sma=dfs(a,b,c,d,1,f);
36         for(int i=2;i<5;i++){
37             sma=min(sma,dfs(a,b,c,d,i,f));
38         }
39         ans+=1.0/tot*sma;
40     }
41     if(!f){
42         double sma=dfs(a,b,c,d,e,1);
43         for(int i=2;i<5;i++){
44             sma=min(sma,dfs(a,b,c,d,e,i));
45         }
46         ans+=1.0/tot*sma;
47     }
48     tmp=ans;
49     return tmp;
50 }
51 int main(){
52     int t,cas=1;
53     while(~scanf("%d",&t)){
54         while(t--){
55             int sum=0;
56             for(int i=0;i<4;i++){
57                 scanf("%d",&s[i]);
58                 if(s[i]>13) sum+=s[i]-13;
59             }
60             printf("Case %d: ",cas++);
61             if(sum>2){
62                 puts("-1.000");
63                 continue;
64             }
65             for(int i=0;i<14;i++){
66                 for(int j=0;j<14;j++){
67                     for(int x=0;x<14;x++){
68                         for(int y=0;y<14;y++){
69                             for(int a=0;a<5;a++){
70                                 for(int b=0;b<5;b++){
71                                     dp[i][j][x][y][a][b]=-1;
72                                 }
73                             }
74                         }
75                     }
76                 }
77             }
78             printf("%.3f\n",dfs(0,0,0,0,0,0));
79         }
80     }
81     return 0;
82 }
View Code

 

 

B - Candles UVA 12368

题意是0123456789这10个数字,每一个可选可不选,最后问最少选几个可构成输入n个数字,如果个数相同则选择倒序的值小的选法。构成一个数字的方法有两种,一种是直接由所选数字构成,一种是构成两个数字之和是输入的数字。

2进制枚举+预处理 2的10次方表示每一位选或者不选

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<algorithm>
  5 #define mt(a,b) memset(a,b,sizeof(a))
  6 using namespace std;
  7 int a[16],digit[16],len[128];
  8 vector<int> sta[128];
  9 void add(int x){
 10     while(x){
 11         digit[x%10]++;
 12         x/=10;
 13     }
 14 }
 15 bool judge(){
 16     for(int i=0;i<10;i++){
 17         if(digit[i]>1) return false;
 18     }
 19     return true;
 20 }
 21 int get(){
 22     int res=0;
 23     for(int i=9;i>=0;i--){
 24         res<<=1;
 25         res|=digit[i];
 26     }
 27     return res;
 28 }
 29 bool test(int x){
 30     mt(digit,0);
 31     add(x);
 32     return judge();
 33 }
 34 bool test(int x,int y){
 35     mt(digit,0);
 36     add(x);
 37     add(y);
 38     return judge();
 39 }
 40 int getone(int x){
 41     int res=0;
 42     while(x){
 43         if(x&1) res++;
 44         x>>=1;
 45     }
 46     return res;
 47 }
 48 int main(){
 49     for(int i=1;i<=100;i++){
 50         sta[i].clear();
 51     }
 52     for(int i=1;i<=100;i++){
 53         if(test(i)){
 54             sta[i].push_back(get());
 55         }
 56         for(int j=1;j+j<=i;j++){
 57             if(test(j,i-j)){
 58                 sta[i].push_back(get());
 59             }
 60         }
 61     }
 62     for(int i=1;i<=100;i++){
 63         sort(sta[i].begin(),sta[i].end());
 64         len[i]=unique(sta[i].begin(),sta[i].end())-sta[i].begin();
 65     }
 66     int n,cas=1,big=1<<10;
 67     while(~scanf("%d",&n),n){
 68         for(int i=0;i<n;i++){
 69             scanf("%d",&a[i]);
 70         }
 71         int ans_cnt=11,ans_sta=0x3f3f3f3f;
 72         for(int i=0;i<big;i++){
 73             int cnt=getone(i);
 74             if(cnt>ans_cnt) continue;
 75             if(cnt==ans_cnt&&i>ans_sta) continue;
 76             bool ok=true;
 77             for(int j=0;j<n;j++){
 78                 bool flag=false;
 79                 for(int k=0;k<len[a[j]];k++){
 80                     int his=sta[a[j]][k];
 81                     if((i&his)==his){
 82                         flag=true;
 83                         break;
 84                     }
 85                 }
 86                 if(!flag){
 87                     ok=false;
 88                     break;
 89                 }
 90             }
 91             if(ok){
 92                 if(ans_cnt>cnt){
 93                     ans_cnt=cnt;
 94                     ans_sta=i;
 95                     continue;
 96                 }
 97                 ans_sta=min(ans_sta,i);
 98             }
 99         }
100         printf("Case %d: ",cas++);
101         for(int i=9;i>=0;i--){
102             if(ans_sta&(1<<i)){
103                 printf("%d",i);
104             }
105         }
106         puts("");
107     }
108     return 0;
109 }
View Code

 

posted on 2015-04-02 18:02  gaolzzxin  阅读(165)  评论(0编辑  收藏  举报