您的位置:首页 > 其它

一个简单题,引发的思索 + nyoj 1189

2015-04-07 15:37 295 查看
题目描述:第一行:给你两个数m和n,m表示有m个数,然后下一行输入m个数,每个数只能选择一次,统计共有多少种情况使得所选数的和大于等于n;

解决本题我想到了两种方法,(题目自己想的,先不考虑超时),第一种dfs(题目自己想的,先不考虑超时)第二种:01背包问题;

dfs 由于递归的结束条件放错了导致最后结果中重复算了很多次,经过分析修改才得出结果;

第一种方法代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int  ans;
int  a[50];
int m , n;
void dfs(int i,int sum)
{
if(i>=m)//一开始错了很久,写成了if(i>=m)  return ;后来发现次数变多了
{
if(sum>=n)
{
//printf("sum == %d\n",sum);
ans++;
}
return ;
}
dfs(i+1,sum); //要
dfs(i+1,sum+a[i+1]);//不要
}
int main()
{
while(cin>>m>>n)
{
ans = 0;
for(int i = 1;i<=m; i++)
scanf("%d",&a[i]);
dfs(0,0);
cout<<ans<<endl;
}
return 0;
}


第二种方法动态规划:状态转移方程 dp[i][j] = dp[i-1][j] + dp[i-1][j-a[i]];

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100;
int dp

;
int a[50];
int m , n;
int main()
{
while(cin>>m>>n)
{ int sum  = 0,ans = 0;
for(int i = 1;i<=m; i++)
{
scanf("%d",&a[i]);
sum = sum + a[i];
}
memset(dp,0,sizeof(dp));
dp[0][0]  = 1;
for(int i = 1; i<=m; i++)
{
for(int j = 0;j<=sum;j++)
{
dp[i][j] = dp[i-1][j]+dp[i-1][j-a[i]];
//printf("i=%d  j=%d %d\n",i,j,dp[i][j]);
}
}
ans = 0;
for(int i = n;i<=sum;i++)
ans = ans +dp[m][i];
printf("%d",ans);
}
return 0;
}


ny1189 题目描述:和上面的描述类似,只不过是把加号变成了 异或和而已,解题思想类似,数据量大,直接开辟数组,存不下,只能压缩,dfs必然会超时

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1100100;
long long dp[3]
;
long long a[50];
int m , n;
int main()
{
int ma;
while(cin>>m>>n)
{ long long ma  = 0;
memset(dp,0,sizeof(dp));
for(int i = 1;i<=m; i++)
{
scanf("%lld",&a[i]);
ma=max(ma,a[i]);//每次都存储最大的值
}
dp[0][0]  = 1;
for(int i = 1; i<=m; i++)
{ memset(dp[i%2],0,sizeof(dp[i%2])); //只是用了两层的循环,这样很简单的减少了空间的用量
for(int j = 0;j<=ma;j++)
{
dp[i%2][j^a[i]] = dp[(i+1)%2][j]+dp[i%2][j^a[i]];//要
dp[i%2][j] = dp[i%2][j] + dp[(i+1)%2][j];//不要
if(ma<(j^a[i]))
ma = (j^a[i]);
}
}
long long ans = 0 ;
for(int i = n;i<=ma;i++)
ans = ans +dp[m%2][i];
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: