zoukankan      html  css  js  c++  java
  • UVA 1252 Twenty Questions(状压DP)

    题目链接:https://vjudge.net/problem/UVA-1252

    题意:有n件物品,每件物品有m个特征,可以对特征进行询问,
    询问的结果是得知某个物体是否含有该特征,要把所有的物品区分出来
    (n个物品的特征都互不相同)最小需要多少次询问?

    题目分析:定义dp(s,a)表示询问了的特征集合为s,
    物体含有特征集合a中的所有特征,但不含特征集合 s^a 中的所有特征时还需的最少询问次数。


    状态转移方程为dp(s,a)=min(max(dp(s|(1<<k),a|(1<<k)),dp(s|(1<<k),a))+1)。
    用记忆化搜索的形式实现即可。
    当这样的物体只有一个或一个没有时,便可区分出所有的物品,此时dp(s,a)=0。

    AC代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 const int INF=1<<30;
     6 const int maxn=1<<11;
     7 int st[130],d[maxn][maxn];
     8 int m,n; 
     9 char ch[13];
    10 int getval(){
    11     int res=0;
    12     for(int i=0;i<strlen(ch);i++)
    13         if(ch[i]=='1')
    14         res=res|(1<<i);
    15     return res;
    16 }
    17 int dp(int s,int a){
    18     if(d[s][a]!=INF) return d[s][a];
    19     int num=0;
    20     for(int i=0;i<n;i++)
    21     if((st[i]&s)==a)  num++;
    22     if(num<=1) return d[s][a]=0;
    23     int &ans=d[s][a];
    24     for(int i=0;i<m;i++){
    25         if(s&(1<<i)) continue; //同一个特征不需要问两遍,s集合存储不一样的特征 
    26         ans=min(ans,max(dp(s|(1<<i),a),dp(s|(1<<i),a|(1<<i)))+1);
    27     }
    28     return ans;
    29 }
    30 int main(){
    31     while(scanf("%d%d",&m,&n)&&m&&n){
    32         for(int i=0;i<n;i++){
    33             scanf("%s",ch);
    34             st[i]=getval();
    35         }
    36         for(int i=0;i<maxn;i++)
    37         for(int j=0;j<maxn;j++)
    38             d[i][j]=INF;
    39         printf("%d\n",dp(0,0));
    40     }
    41 }
    View Code
  • 相关阅读:
    Android Activity
    Android 五大布局
    Android 使用线性布局LinearLayout和Button实现一个点红块游戏
    邻接表、逆邻接表
    view的绘制原理
    IPC机制
    图的深度优先遍历
    最短路径算法
    几种编码方式
    Android APK反编译问题
  • 原文地址:https://www.cnblogs.com/djh0709/p/9588376.html
Copyright © 2011-2022 走看看