奋斗群群赛6总结与心得

来源:互联网 发布:淘宝网连衣裙图片 编辑:程序博客网 时间:2024/05/18 16:37

  • 总体情况
  • T1
    • 题目
    • 思路
  • T2
    • 题目
    • 思路
  • T3
    • 题目
    • 思路
  • T4
    • 思路

总体情况

https://cn.vjudge.net/contest/184118
前两题很简单,第三题我会暴力,成功TLE;第四题看不懂算了。

T1

题目

输入一个正整数n,输出两个数a,b,a < b,a+b=n,a与b互质并且保证a最大。

思路

简单到可怕的水题。从中间开始搜,搜到两个数是互质的直接停止。

#include<bits/stdc++.h>using namespace std;int main(){int n,i;cin>>n;for (i=n/2;i>=1;i--) if (__gcd(i,n-i)==1)  {  cout<<i<<" "<<n-i;  return 0;  }}

T2

题目

一路上并排着n座房子,其中k座已经住了人。对于空着并且相邻的房子中至少有一座已经住人的房子,我们称为“好房”。给出n,k,输出“好房”最少和最多有多少栋。

思路

k==0||k==n的时候最少0栋,因为没有房子住人或者都住满了。其他情况所有住人的房子全部靠在一边,最少1栋。当已经住人的房子较少的时候(k<=n/3)我们令住人的房子在2,5,8,11……这样好房最多。当k>n/3的时候所有剩下的房子都可以是好房,输出n-k.

#include<bits/stdc++.h>using namespace std;int main(){int n,k,xiao,da;cin>>n>>k;if (k<n&&k!=0) xiao=1;else xiao=0;if (k<=n/3) da=k*2;else if (k!=0) da=n-k;else da=0;cout<<xiao<<" "<<da;}

T3

题目

n架飞机,出发时间分别为1,2,3,4,5……,现在机场出了故障,所有的飞机的出发时间按顺序延迟k,变为k+1,k+2……对于每一架飞机,延迟m单位时间的代价是a[i]*m,但是你可以调整飞机的出发顺序,使得代价最小.还有一点,调整出发顺序的时候每一架飞机的出发时间不能在它在晚点之前的出发时间之前.输入n,k输出最小的代价和各飞机的出发时间(出发时间spj,使得代价最小)

思路

看到题我觉得这个题是动态规划,但是我不会,所以我放弃了.我想到这是一个各飞机出发时间的全排列,我就准备好暴力了.300000的数据,这个复杂度惊人啊,但是答案是对的,成功地T了.

#include<bits/stdc++.h>using namespace std;int a[300010],b[300010],k,n,minflight[300010];bool used[300010];long long xiao=999999999999999;void dfs(int m){int i;long long s=0;if (m>n)  {  for (i=1;i<=n;i++) s+=(b[i]-i+k)*a[i];  xiao=min(xiao,s);   if (s==xiao) for (i=1;i<=n;i++) minflight[i]=b[i]+k;  } else for (i=1;i<=n;i++) if (used[i]==0&&i+k>=m)//保证出发时间在原出发时间之前  {  b[m]=i;  used[i]=1;  dfs(m+1);  used[i]=0;  }}int main(){int i;cin>>n>>k;for (i=1;i<=n;i++) scanf("%d",&a[i]);dfs(1);printf("%lld\n",xiao);for (i=1;i<=n;i++) printf("%d ",minflight[i]);}

后来我想到这是一个贪心,在保证题目要求的情况下每次取最大值,放在最前面。每次取最大值可以用sort,但是无法把它和飞机原定出发时间放在一起。我觉得可以建一个堆(优先队列),用一个pair存放代价和出发时间。代码如下。

#include<bits/stdc++.h>using namespace std;priority_queue<pair<int,int> > q;//建堆,比较first自动排序long long result[300010]; int main(){long long n,k,i,planetime,sum=0;cin>>n>>k;for (i=1;i<=n+k;i++)   {  if (i<=n)    {    cin>>planetime;    q.push({planetime,i});    }  if (i>k)    {    result[q.top().second]=i;//代价最大的放在最前面    sum+=(q.top().first*(i-q.top().second));//计算出代价求和    q.pop();//弹出最大值    }  }cout<<sum<<endl;for (i=1;i<=n;i++) cout<<result[i]<<" ";}

T4

思路

看代码吧.

#include<bits/stdc++.h>#define boss 1000000#define index 233333333333using namespace std;typedef long long ll;struct ren{int sei,huafei;};vector<ren> v[2][boss+233];ll f[boss+233],mi[boss+233]={0},answer,result=index;int n,m,k;void nico(ren a){if (mi[a.sei]>a.huafei) answer-=(mi[a.sei]-a.huafei),mi[a.sei]=a.huafei;}int main(){int i;scanf("%d%d%d",&n,&m,&k);for (int d,x,y,z;m--;v[!!y][d].push_back((ren){x+y,z})) scanf("%d%d%d%d",&d,&x,&y,&z);for (i=1;i<=n;i++) mi[i]=index;for (answer=index*n,i=1;i<=boss;f[i]=answer,i++) for (int j=0;j<(int)v[0][i].size();j++) nico(v[0][i][j]);for (i=1;i<=n;i++) mi[i]=index;for (answer=index*n,i=boss;i;result=min(result,(ll)i-k-1>0?answer+f[i-k-1]:index),i--) for (int j=0;j<(int)v[1][i].size();j++) nico(v[1][i][j]);if (result==index) result=-1;cout<<result;}