zoukankan      html  css  js  c++  java
  • 10.21T8 rand()随机化/背包

    Description

    N(1 <= N <= 20)个干草堆,每堆的体积大小为Si(1 <= Si <= 100),需要分装到三个谷仓里。要求这三谷仓分得尽量平均(每堆草不可分割),即最大的一堆最小。请求出这最大的一个谷仓分得的体积。

    Input

    第一行: 整数 N.
    第 2..1+N行:每行一个整数表示第第i堆的体积Si.

    Output

    第1行:最大谷仓分得的干草堆体积和

    Sample Input

    8
    14
    2
    5
    15
    8
    9
    20
    4

    Sample Output

    26
     
     
     
    此题使用堆然后直接看人品随机化就可以了
    23333333
    使用我的生日20020731做种子就AC了哈哈哈哈哈哈
    code:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<ctime>
     5 #include<cstdlib>
     6 using namespace std;
     7 priority_queue<int,vector<int>,greater<int> >q;
     8 int a[30];
     9 int main() {
    10     srand(20020731);
    11     int n;
    12     cin>>n;
    13     for(int i=1; i<=n; i++) {
    14         cin>>a[i];
    15         q.push(a[i]);
    16     }
    17     int min0=0x3f3f3f3f;
    18     for(int o=1; o<=1200000; o++) {
    19         int b[3]= {0,0,0},max0=0;
    20         for(int i=1; i<=n; i++) {
    21             int now=q.top();
    22             q.pop();
    23             b[(rand())%3]+=now;
    24         }
    25         max0=max(b[0],max(b[1],b[2]));
    26         min0=min(min0,max0);
    27         for(int i=1; i<=n; i++) {
    28             q.push(a[i]);
    29         }
    30     }
    31     cout<<min0;
    32     return 0;
    33 }

    当然我们除此之外还有背包算法

    令f[i][j]表示第一个谷仓体积为i,第二个为j是否存在,于是我们就可以直接暴力跑背包

    当然因为转移的时候好像为了避免滚动数组的思考难度就用了两个数组复用

    code:

     1 #include <iostream>
     2 using namespace std;
     3 const int MAXS = 700;
     4 
     5 int n, bale, tsum;
     6 bool good[2][MAXS+100][MAXS+100];
     7 
     8 int main()
     9 {
    10     for (int i = 0; i < 2; i++)
    11         for (int j = 0; j < MAXS; j++)
    12             for (int k = 0; k < MAXS; k++)
    13                 good[i][j][k] = false;
    14     good[0][0][0] = true;
    15     tsum = 0;
    16 
    17     fin >> n;
    18     for (int i = 0; i < n; i++)
    19     {
    20         fin >> bale;
    21         tsum += bale;
    22         for (int j = 0; j < MAXS; j++)
    23             for (int k = 0; k < MAXS; k++)
    24             {
    25                 if (good[i%2][j][k])
    26                 {
    27                     good[(i+1)%2][j][k] = true;
    28                     good[(i+1)%2][j+bale][k] = true;
    29                     good[(i+1)%2][j][k+bale] = true;
    30                 }
    31             }
    32     }
    33 
    34     int ans = MAXS;
    35     for (int i = 0; i < MAXS; i++)
    36         for (int j = 0; j < MAXS; j++)
    37             if (good[n%2][i][j])
    38                 ans = min (ans, max (i, max (j, tsum - (i + j))));
    39     fout << ans <<"
    ";
    40     return 0;
    41 }

    爆搜也是可以的

    code:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int a[25],n,ans=0x7fffffff;
     5 void dfs(int k,int x,int y,int z){
     6     if(k==n+1){ans=min(ans,max(max(x,y),z));return ;}
     7 //可行性减枝
     8     if(ans-a[k]>x)dfs(k+1,x+a[k],y,z);
     9     if(ans-a[k]>y&&x!=y)dfs(k+1,x,y+a[k],z);
    10     if(ans-a[k]>z&&x!=z&&y!=z)dfs(k+1,x,y,z+a[k]);
    11 }
    12 int main(){
    13     scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    14     dfs(1,0,0,0);printf("%d",ans);
    15     return 0;
    16 }

    神仙做法:排完序之后可以交换

    code:

     1 #include<iostream>
     2 #include<iomanip>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 int n;
     9 int s[200]={0};
    10 int minv[3];
    11 int ob[3][200]={0};
    12 int cnt[3]={0};
    13 bool cmp(int a,int b){return a>b;}
    14 int get_maxpos(){int maxpos,vmax=0;for(int k=0;k<=2;k++)if(minv[k]>vmax){maxpos=k;vmax=minv[k];}return maxpos;}
    15 int get_minpos(){int minpos,vmin=0x7fffffff;for(int k=0;k<=2;k++)if(minv[k]<vmin){minpos=k;vmin=minv[k];}return minpos;}
    16 void tiaozheng(int a,int b){//通过枚举交换a,b的物品,使最大值最小 
    17     bool mark=0;
    18     for(int i=1;i<=cnt[a];i++){
    19         for(int j=1;j<=cnt[b];j++){
    20             if(max(minv[a]-ob[a][i]+ob[b][j],minv[b]-ob[b][j]+ob[a][i])<max(minv[a],minv[b])){//如果交换后最大值最小 
    21                 minv[a]=minv[a]-ob[a][i]+ob[b][j];
    22                 minv[b]=minv[b]-ob[b][j]+ob[a][i];
    23                 swap(ob[a][i],ob[b][j]);//交换两个物品 
    24                 mark=1;//标记交换过 
    25             }
    26         }
    27     }
    28     if(!mark)return;//如果之前有交换,继续交换最大和最小 
    29     int maxpos=get_maxpos(),minpos=get_minpos();
    30     if(minpos!=maxpos)tiaozheng(minpos,maxpos);
    31 }
    32 int main(){
    33     scanf("%d",&n);
    34     for(int i=1;i<=n;i++)scanf("%d",&s[i]);
    35     
    36     sort(s+1,s+n+1,cmp);//按从大到小排序 
    37 
    38     minv[0]=s[1];//初始赋值 
    39     ob[0][1]=s[1];
    40     cnt[0]=1;
    41     //每步都保证当前最优 
    42     for(int i=2;i<=n;i++){
    43         int maxpos,minpos=get_minpos();//得到当前最小位置,加入s[i] 
    44         minv[minpos]+=s[i];
    45         cnt[minpos]++;
    46         ob[minpos][cnt[minpos]]=s[i];
    47         maxpos=get_maxpos();minpos=get_minpos();
    48         if(minpos!=maxpos)tiaozheng(minpos,maxpos);//先交换最大的和最小的
    49         tiaozheng(0,1);//尝试交换既不是最大也不是最小的
    50         tiaozheng(2,1);
    51         tiaozheng(0,2);
    52     }
    53     int ans=0;
    54     ans=max(minv[0],minv[1]);
    55     ans=max(ans,minv[2]);
    56     cout<<ans;
    57     return 0;
    58 }

    over  哈哈哈哈哈哈哈哈哈哈哈哈嗝

  • 相关阅读:
    node分离路由文件
    node项目搭建步骤
    在express获取POST(类似表单请求)的数据
    10分钟搭建Kubernetes容器集群平台(kubeadm)
    今日考题
    jQuery方法介绍
    JQuery练习题
    今日面试题:
    bom操作,事件与jquery
    今日理解之js
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9827253.html
Copyright © 2011-2022 走看看