In each case, there are two numbers in the first line n (the size of the set) and H. The second line has n numbers {a[1],a[2],......,a[n]}. 0<n<=40, 0<=H<10^9, 0<=a[i]<10^9,All the numbers are integers.
10 87 2 3 4 5 7 9 10 11 12 13 10 38 2 3 4 5 7 9 10 11 12 13
No Yes
题意:输入 n.h,下面一行有n个数,从这n个数中任选几个数,看着几个数能不能和等于 h,若能就输出Yes 否则就输出No
这是我比赛时的思路,但是没有那个sum【】数组减值,但是我是用 tt[x-1]<=a[i]和book数组标记 ,这样避免重复的(像1,2,3,或3,2,1,或2,1,3等6种排列只能出现一种),这样时间复杂度太高了,但当时那个代码是个 wa,不也不知道哪出错了,(不要再想那个代码了,没意义,下面有更好的)但是那个代码要改进的地方太多了,就像为了避免重复,就定义一个top,让 top 之前的不能再次入栈,这样避免从重复(比上面那个好(时间复杂度低)),我又加了sum[] 数组减值,提交不知道为啥是 0 ms ,可能是后台数据太水了
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 50
long long book[Max];
long long a[Max],n,h,f,s[Max];
void dfs(long long top,long long x ,long long sum) //top 之前的不会再入栈,所以根本就不用book数组标记
{ // x-1 为已经加了几个数了,sum为这几个数的和;
if(sum==h||f)
{
f = 1;
return ;
}
if(x>n)
{
f = 2;
return ;
}
for(long long i = top; i<=n; i++)
{
if(sum+(s[n]-s[i-1])<h) // 这个减值挺好,以后一定要思考减值;
return ;
if(sum+a[i]>h)
continue;
dfs(i+1,x+1,sum+a[i]);
if(f) return ;
}
}
int main()
{
while(~scanf("%lld%lld",&n,&h))
{
for(long long i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
if(i==1) s[i] = a[i];
else s[i] = s[i-1] + a[i];
}
f = 0;
memset(book,0,sizeof(book));
dfs(1,1,0);
if(f==1) printf("Yes\n");
else printf("No\n");
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 50
long long sum[Max],a[Max],n,h,f;
void dfs(long long top,long long ans)
{
if(ans==h)
{
f=1;
return ;
}
if(top>n||ans>h||ans+(sum[n]-sum[top-1])<h) //减值
return ;
dfs(top+1,ans);
if(f) return ;
dfs(top+1,ans+a[top]);
if(f) return ;
}
int main()
{
long long i,j;
while(~scanf("%lld%lld",&n,&h))
{
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(i==1) sum[i] = a[i];
else sum[i] = sum[i-1] + a[i];
}
f = 0;
dfs(1,0);
if(f) printf("Yes\n");
else printf("No\n");
}
return 0;
} 以后遇到这样的题先想想能不能定义光标top,让光标移动,让每一栈中的调用函数(递归)变少,这道题就是选不选的问题;
6667



被折叠的 条评论
为什么被折叠?



