以后博客以后不应该只是记录些学习知识,应该还有些更重要的东西........
我觉得应该去思考一些什么东西.......
有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式。如:
n=5,5个数分别为1,2,3,4,5,t=5;
那么可能的组合有5=1+4和5=2+3和5=5三种组合方式。
输入
输入的第一行是两个正整数n和t,用空格隔开,其中1<=n<=20,表示正整数的个数,t为要求的和(1<=t<=1000)
接下来的一行是n个正整数,用空格隔开。
输出
和为t的不同的组合方式的数目。
样例输入
5 5
1 2 3 4 5
样例输出
3
这个暴力......
#include<iostream> using namespace std; int a[100010],ans=0; int n,m; void dfs(int d,int num) { if(d==n+1) { if(num==m)ans++; return ; } dfs(d+1,num+a[d]); dfs(d+1,num); } int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; dfs(1,0); cout<<ans<<endl; return 0; }
其实这是个背包问题,这个是二维和一维的
#include<bits/stdc++.h> using namespace std; int n,m; int a[1000]; int dp[1000]; int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; /* for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i]>j) dp[i][j]=dp[i-1][j]; else dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]]; } for(int j=1;j<=m;j++) cout<<dp[i][j]<<" "; cout<<endl; }*/ for(int i=1;i<=n;i++) { dp[0]=1; for(int j=m;j>=a[i];j--) { dp[j]=dp[j]+dp[j-a[i]]; } for(int j=1;j<=m;j++) cout<<dp[j]<<" "; cout<<endl; } cout<<dp[m]; return 0; }
背包问题最进又看了下
for(int i=1;i<=n;i++) { for(int j=v;j>=0;j--) { if(w[i]<=j) f[j]=max(f[j],f[j-w[i]]+c[i]) else f[j]=f[j]; } } for(int i=0;i<n;i++) { for(int j=w[i];j<=v;j++) { if(w[i]<j) f[j]=max(f[j],f[j-w[i]]+c[i]); else f[j]=f[j]; } } void zeroonepack(int cost,int weight) { for(int i=V;i>=cost;i--) f[i]=max(f[i],f[i-cost]+weight); } void completepack(int cost,int weight) { for(int i=cost;i<=V:i++) f[i]=max(f[i],f[i-cost]+weight); } void multiplepack(int cost,int weight,int mount) { int k; if(cost*mount>=V) { completepack(cost,weight); return; } k=1; while(k<mount) { zeroonepack(k*cost,k*weight); mount-=k; k*=2; } zeroonepack(mount*cost,mount*weight); } int main() { int n,i; cin>>n>>V; for(int i=0;i<n;i++) cin>>m+i>>c+i>>w+i; for(int i=0;i<n;i++) multiplepack(c[i],w[i],m[i]); cout<<f[v]; }
n个数和m,求最小连续序列和大于m
#include<iostream> #include<string.h> #define ll long long using namespace std; ll a[1000005]; int main() { int t; scanf("%d",&t); while(t--) { ll n,m; scanf("%lld%lld",&n,&m); a[0]=0; for(ll i=1;i<=n;i++) { scanf("%lld",&a[i]); a[i]+=a[i-1]; } ll ans=0x3f3f3f; for(ll i=1;i<=n;i++) { ll l=1,r=i,mid; while(l<=r) { mid=(l+r)>>1; if(a[i]-a[mid-1]>=m) { // cout<<a[i]<<" "<<a[mid-1]<<"xxxxx"<<r-mid+1<<endl;; ans=min(ans,(i-mid+1)); l=mid+1; } else r=mid-1; } } if(ans==0x3f3f3f) cout<<0<<endl; else cout<<ans<<endl; } }
记忆化搜索
#include<bits/stdc++.h> using namespace std; int n,k,dp[105][105],a[105][105]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int dfs(int x,int y) { int l,ans=0; if(dp[x][y]!=0) return dp[x][y]; for(int i=1;i<=k;i++) { for(int j=0;j<4;j++) { int xx=x+dx[j]*i; int yy=y+dy[j]*i; if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&a[xx][yy]>a[x][y]) ans=max(ans,dfs(xx,yy)); } } dp[x][y]=ans+a[x][y]; return dp[x][y]; } int main() { while(cin>>n>>k) { if(n<=0&&k<=0) break; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin>>a[i][j]; } } memset(dp,0,sizeof(dp)); cout<<dfs(1,1)<<endl; } }