【UVA11205】The broken pedometer,思路+代码,可能是最不装逼最朴素最易懂效率也最差的代码。

7 篇文章 0 订阅
4 篇文章 0 订阅
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
/**
    Problem : UVA11205 - The broken pedometer
    Begin Time: 28th/Mar/2012 11:30 a.m.
    Finish Time: 29th/Mar/2012 2:14 a.m.
    Last Time : About 6 hours.
    State:9924407	11205	The broken pedometer	Accepted	C++	2.684	2012-03-28 18:11:32
    Knowledge : BFS,剪枝都没有,还有子集生成,也算有个小小的状态压缩?
    Exp.: WA * 4 :这四个Wrong Answer奉献给了误把BFS写成DFS,不应该
          WA * 4 :我他妈对于后四个WA无力吐槽了啊我操。边界,边界!
                    tmp.depth + 1 <= col写成了 tmp.depth + 1 < col结果就少了一组组合啊!过脑子啊白痴!写程序时。
                    操操操操操。
    Thought:
            每行换成10110101这样的整数(因为最多才2^15,不用位运算了,否则怪麻烦的)
            开一个数组isSel[],如果ith列被选了那么isSel[i] = true;
            然后根据isSel判断目前选的列数,以及应该从那几列中抽取子集。
            其实位运算能快一些。
    Summerize:
            发现搜索出错的时候
            1.仔细想一下搜索的过程,状态转移的方式,是否有状态结点未展开
            2.想一下边界,是否有问题
            最重要的,写之前看清楚了,一般有最短,最少,最小字样的统统为BFS.
            搜索的如果是个树,则不需要回溯,如果是个图,则需要回溯。
*/
const int MAXN = 200;
const int MAXP = 50;
int puzzle[MAXN][MAXP];
int subset[MAXN];
bool isSel[MAXN];
int minN;
bool isFound;
struct node
{
    int depth;
    bool isSel[MAXN];
};
node tmp;
queue<node> que;
int comp(const void *a, const void *b)
{
    return (*(int*)a - *(int*)b);
}
bool check(int row,int col)
{
    int cnt = 0;

    memset(subset,0,sizeof(subset));
    for(int i = 0 ; i < col ; i++)
    {
        if(isSel[i] == true)
            cnt++;
    }

    for(int j = 0 ; j < row ; j++)
    {
        for(int i = 0 ; i < col ; i++)
        {
            if(isSel[i] == true )
            {
                subset[j] = subset[j] * 10 + puzzle[j][i];
            }
        }
    }

    qsort(subset,row,sizeof(int),comp);

    int i = 0;
    int j = i+1;
    while( j < row )
    {
        if(subset[i] == subset[j])
        {
            return false;
        }
        i++,j++;
    }
    if( minN > cnt)
    {
        minN = cnt;
    }
    return true;
}
int Solve(int row,int col,int now)
{
    node tmp,tmp1,k;
    while(!que.empty())
    {
        tmp=que.front();
        que.pop();
        memcpy(isSel,tmp.isSel,sizeof(isSel));
        tmp1 = tmp;
        check(row,col);
        if(tmp.depth + 1  <= col)
        {
            tmp1.depth = tmp.depth + 1;
            tmp1.isSel[tmp1.depth - 1] = false;
            que.push(tmp1);
            tmp1.isSel[tmp1.depth - 1] = true;
            que.push(tmp1);
        }
    }
    return minN;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("b:\\acm\\UVA\\UVA11205\\input.txt","r",stdin);
    freopen("b:\\acm\\uva\\uva11205\\output.txt","w",stdout);
#endif
    int T,P,N,k;
    //  while( scanf("%d",&T) != EOF )
    scanf("%d",&T);
    {
        for(int t = 1 ; t <= T ; t++)
        {
            scanf("%d%d",&P,&N);
            memset(puzzle,0,sizeof(puzzle));
            memset(subset,0,sizeof(subset));
            memset(isSel,0,sizeof(isSel));
            for(int i = 0 ; i < N ; i++)
            {
                for(int j = 0 ; j < P ; j++)
                {
                    scanf("%d",&puzzle[i][j]);
                }
            }
            minN = 200;

            tmp.depth = 1;
            tmp.isSel[0] = true;
            que.push(tmp);

            tmp.depth = 1;
            tmp.isSel[0] = false;
            que.push(tmp);

            k = Solve(N,P,0);
            printf("%d\n",k);
            while(!que.empty())
            {
                que.pop();
            }
        }

    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值