本文章基于《计蒜客蓝桥杯省赛2019训练营》整理记录,并由个人对部分内容进行补充说明。文章仅用于个人学习交流使用。
1.蒜头君的购物袋1
//蒜头君的购物袋
#include<iostream>
#include<cstring>
using namespace std;
int max(int x,int y){
return x>y?x:y;
}
int main(){
int n,v;
cin>>n>>v;
int a[n];
int dp[v+1];
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++){
cin>>a[i];
for(int j=v;j>=a[i];j--){
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
}
cout<<v-dp[v]<<endl;
return 0;
}
2.蒜头君的存钱罐
//存钱罐
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e4+5;
const int inf=0x3f3f3f3f;//无穷大量
int f[N];
int main(){
memset(f,inf,sizeof(f));
f[0]=0;
int a,b;
cin>>a>>b;
int v=b-a;
int n;
cin>>n;
int x,y;
for(int i=0;i<n;i++){
cin>>x>>y;
for(int j=y;j<=v;j++){
f[j]=min(f[j],f[j-y]+a);
}
}
if(f[v]==inf){
cout<<"no"<<endl;
}else{
cout<<f[v]<<endl;
}
return 0;
}
/*
--cin:
1 6
2
10 3
20 4
--cout:
no
*/
3.平分娃娃
//平分娃娃
#include<iostream>
using namespace std;
int f[200010],a[10];
int main() {
int sum=0;
for(int i=1; i<=6; i++) {
cin>>a[i];
sum+=a[i]*i;
}
if(sum&1) { //奇数
cout<<"no"<<endl;
return 0;
}
sum>>=1; //除以二
for(int i=1; i<=6; i++) { //多重背包
int k;
for(k=1; k*2<1+a[i]; k<<=1) { //二进制枚举 ( 能够优化时间)
for(int j=sum; j>=i*k; j--) {
f[j]=max(f[j],f[j-i*k]+i*k);
}
}
k=a[i]-k+1;
for(int j=sum; j>=i*k; --j) {
f[j]=max(f[j],f[j-i*k]+i*k);
}
}
if(sum==f[sum]) {
cout<<"yes"<<endl;
}
return 0;
}
/*
--cin:
2 2 2 2 2 2
--cout:
yes
*/
4.等和的分割子集
//等和的分割子集
#include<iostream>
using namespace std;
long long dp[4000];
int main(){
int n;
cin>>n;
int sum=n*(n+1)/2;
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=sum;j>=i;j--){
dp[j]+=dp[j-i];
}
}
if(sum%2==1){
cout<<"0"<<endl;
}else{
cout<<dp[sum/2]/2<<endl;
}
}
/*
--cin:
7
--cout:
4
*/
5.饭卡
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e3+9;
int a[1010],f[N];
int main(){
int n,m;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
cin>>m;
memset(f,0,sizeof(f));
f[0]=1;
sort(a,a+n);
int ma=0;
for(int i=0;i<n;i++){
for(int j=m-5;j>=0;j--){
if(f[j]){
f[j+a[i]]=1;
ma=max(ma,j+a[i]);
}
}
}
cout<<m-ma<<endl;
return 0;
}
6.整数划分
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1e3+9;
const int mod=1e9+9;
int f[N];
int main() {
int t;
cin>>t;
while(t--) {
memset(f,0,sizeof f);
f[0]=1;
int n;
cin>>n;
for(int i=1; i<=n; i++) {
for(int j=i; j<=n; j++) {
(f[j]+=f[j-i])%=mod;
}
}
cout<<f[n]<<endl;
}
return 0;
}
/*
--cin:
1 6
--cout:
11
*/
7.蒜头君的offer
//offer
#include<iostream>
using namespace std;
const int N=1e4+9;
double f[N];
int main(){
int n,m;
cin>>n>>m;
int x;
double y;
while(m--){
cin>>x>>y;
for(int j=n;j>=x;j--){
f[j]=max(f[j],1.0-(1-f[j-x])*(1-y));
}
}
printf("%.1lf%%\n",f[n]*100);
return 0;
}
/*
--cin:
10 3
4 0.1
4 0.2
5 0.3
--cout:
44.0%
*/
8.新年趣事之打牌
//过年趣事之打牌
#include<iostream>
using namespace std;
const int N=1e5+9;
int f[N]={0},path[N],a[110];
int n,total,sum=0,res;
void print(int url){
if(url){
print(url-a[path[url]]);
if(url==res){
cout<<path[url]<<endl;
}else{
cout<<path[url]<<" ";
}
}
}
int main(){
cin>>total>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
f[0]=1;
res=sum-total;
for(int i=1;i<=n;i++){
for(int j=res;j>=a[i];j--){
f[j]+=f[j-a[i]];
if(f[j]>100){
f[j]=10;
}
if(!path[j]&&f[j-a[i]]){
path[j]=i;
}
}
}
if(!f[res]){
cout<<0<<endl;
}else if(f[res]>1){
cout<<-1<<endl;
}else{
print(res);
}
return 0;
}
9.猫狗大战
#include<iostream>
#include<algorithm>
using namespace std;
const int N=209;
int a[N],f[N][N*20];
int main(){
int n,sum=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
f[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=n/2+1;j>=0;j--){
for(int k=sum/2;k>=0;k--){
if(f[j][k]){
f[j+1][k+a[i]]=1;
}
}
}
}
for(int i=sum/2;i>=0;--i){
if(f[n/2][i] || f[n/2+1][i] && n & 1 ){
cout<<i<<" "<<sum-i<<endl;
break;
}
}
return 0;
}
10.搭建双塔
#include<iostream>
#include<cstring>
using namespace std;
int f[110][2003],h[110];
int main(){
int n,sum=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>h[i];
}
memset(f,-1,sizeof f);
f[0][0]=0;
for(int i=1;i<=n;i++){
sum+=h[i];
for(int j=0;j<=sum;j++){
if(f[i-1][j]>f[i][j]){
f[i][j]=f[i-1][j];
}
if(j>=h[i]&&f[i-1][j-h[i]]>=0){
f[i][j]=max(f[i][j],f[i-1][j-h[i]]);
}
if(f[i-1][j+h[i]]>=0){
f[i][j]=max(f[i][j],f[i-1][j+h[i]]+h[i]);
}
if(h[i]>=j && f[i-1][h[i]-j]>=0){
f[i][j]=max(f[i][j],f[i-1][h[i]-j]+h[i]-j);
}
}
}
if(f[n][0]){
cout<<f[n][0]<<endl;
}else{
cout<<"no"<<endl;
}
return 0;
}
/*
--cin:
5
1 3 4 5 2
--cout:
7
*/