您的位置:首页 > 编程语言 > C语言/C++

hdu5339-Untitled // BestCoder Round #49 ($) 1001 (搜索)

2015-08-02 23:05 459 查看

原链接:http://acm.hdu.edu.cn/showproblem.php?pid=5339

题意:给n个数bi,从中取r个,使得a依次对它们取余的结果为零,问r最小是多少。
ps: 比赛的时候觉得第一题多少应该是个简单题,就想着模拟一下,就一直在找规律,就一直想着怎么变成0,最后还是觉得得用bfs,但又觉得第一题这么做是不是有些麻烦,因为五分钟左右好几个人都做出来了,但是别的又想不出,就先这么做了。结果并没有特别想明白就下手了,导致一个简单的思路写了一个多小时。。唉,还是要理清思路再下手啊。。
思路:
<1> bfs 将a赋给结果res,接下来用每次的结果再对所有bi取余,直到结果为零时跳出,返回步骤次数,否则返回-1,即为结果。
<pre class="cpp" name="code">#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstring>
#include <utility>
#define ll long long
#define INF 0x3f3f3f3f

using namespace std;

int n,a,b[25],bb[25];

struct node
{
int x;
int step;
};

int bfs()
{
queue<node> que;
node s;
s.x=a;
s.step=0;
que.push(s);

while(que.size())
{
node temp=que.front();
que.pop();
if(temp.x==0) return temp.step;

node tep=temp;
for(int i=0;i<n;i++)
{
tep.x=temp.x%b[i];
if(tep.x==temp.x) continue;//重点! 1.排除重复项(也避免了死循环) 2.顺便剪枝
tep.step=temp.step+1;
que.push(tep);
}
}
return -1;
}

int main()
{
int t,res;
cin>>t;
while(t--)
{
cin>>n>>a;
for(int i=0;i<n;i++) scanf("%d",&b[i]);
res=bfs();
printf("%d\n",res);
}
return 0;
}




其实后来想想bfs还是很合情合理的,毕竟算是求最短路径。不过后来看了各位大神的代码,发现都和我不一样。。大多数人选择了dfs。
他们都抓住了一个特点,取余时,余数永远小于除数,所以取出的b序列必定是递减的。

<2> dfs
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstring>
#include <utility>
#define ll long long
#define INF 0x3f3f3f3f

using namespace std;

int ans,b[22];

void dfs(int i,int res,int c) //i 剩余b个数;res 计算结果;c 次数;
{
if(c>=ans) return ; //最先判断,剪枝

if(res==0)
{
ans=c; //保证了 c>=ans,保留结果
return ;
}

if(i==0) return ;

dfs(i-1,res,c);
dfs(i-1,res%b[i],c+1);
}

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,a;
scanf("%d%d",&n,&a);
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
}

sort(b+1,b+1+n);

ans=INF; //赋极大值,但我总觉得这个不保险,如果数据特别大的时候=.=
dfs(n,a,0);

if(ans==INF)ans=-1;
printf("%d\n",ans);
}
return 0;
}


<3>然后惊奇的又发现了dp..dp的思维渣渣的大脑真的不敢恭维- -
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstring>
#include <utility>
#define ll long long
#define INF 0x3f3f3f3f

using namespace std;

int dp[1000010];
int num[30];

int main()
{
int T,m,a;
scanf("%d",&T);
for(int t=1;t<=T;t++)
{
scanf("%d%d",&m,&a);
for(int i=1;i<=m;i++) scanf("%d",&num[i]);
for(int i=0;i<=a;i++) dp[i]=1e9;

dp[a]=0;
for(int i=a;i>=0;i--) //dp[i]保留结果为i时的最短步数
if(dp[i]>=0)
{
for(int j=1;j<=m;j++)
dp[i%num[j]]=min(dp[i%num[j]],dp[i]+1);
}

if(dp[0]<1e9)
printf("%d\n",dp[0]);
else
printf("-1\n");
}
return 0;
}

看大神们的代码真的可以学到好多!
虽然只是简单的搜索题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm hdu c++ 搜索 dp