一个简单题,引发的思索 + nyoj 1189
2015-04-07 15:37
295 查看
题目描述:第一行:给你两个数m和n,m表示有m个数,然后下一行输入m个数,每个数只能选择一次,统计共有多少种情况使得所选数的和大于等于n;
解决本题我想到了两种方法,(题目自己想的,先不考虑超时),第一种dfs(题目自己想的,先不考虑超时)第二种:01背包问题;
dfs 由于递归的结束条件放错了导致最后结果中重复算了很多次,经过分析修改才得出结果;
第一种方法代码:
第二种方法动态规划:状态转移方程 dp[i][j] = dp[i-1][j] + dp[i-1][j-a[i]];
ny1189 题目描述:和上面的描述类似,只不过是把加号变成了 异或和而已,解题思想类似,数据量大,直接开辟数组,存不下,只能压缩,dfs必然会超时
代码:
解决本题我想到了两种方法,(题目自己想的,先不考虑超时),第一种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; }
相关文章推荐
- NYOJ-330 一个简单的数学题
- 由一个简单的String c=a+b的Java问题引发一点想法 推荐
- nyoj 330 一个简单的数学题
- nyoj1110 一个简单数学题
- nyoj-330-一个简单的数学题
- WinForm:一个登陆窗体引发的问题系列(一):最简单的登陆窗口
- Visual Studio 2010中GetMenu()和GetSubMenu(0)引发异常的一个简单解决方法
- 由一个简单登录模块引发的安全危机
- 一个简单的特效引发的大战之移动开发中我为什么放弃jquery mobile
- Visual Studio 2010中GetMenu()和GetSubMenu(0)引发异常的一个简单解决方法
- 一个sql脚本引发的灾难后的思索
- 一个sql脚本引发的灾难后的思索
- 一个简单的shell面试题引发的总结
- 停止标记NYOJ 一个简单的数学题 南工330停止标记
- 由一个简单的客户端间TCP/UDP通信程序引发的关于设计模式的思考
- Access violation reading location 0x00000004--Visual Studio 2010中GetMenu()和GetSubMenu(0)引发异常的一个简单解决方法
- nyoj 一个简单的数学题
- C# 一个简单的秒表引发的窗体卡死问题
- 由一个JMS简单例子引发的思考