Recently, Losanto find an interesting Math game. The rule is simple: Tell you a number
H, and you can choose some numbers from a set {a[1],a[2],......,a[n]}.If the sum of the number you choose is
H, then you win. Losanto just want to know whether he can win the game.
There are several cases.
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.
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.
If Losanto could win the game, output "Yes" in a line. Else output "No" in a line.
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,让光标移动,让每一栈中的调用函数(递归)变少,这道题就是选不选的问题;