以下题目皆为洛谷网站中的题目,可按题号查找
P1007 独木桥
1.思路:贪心,易发现最长时间是所有士兵从自身这点到桥两端的更长的距离取最大值,最短距离就是所有士兵从离桥近的一端下桥
2.代码:
#include<bits/stdc++.h>
using namespace std;
int b[10005];
int a[5005];
int main()
{
int l;
cin>>l;
int n;
cin>>n;
if(n==0)
{
cout<<0<<" "<<0;
}
else
{
for(int i=1;i<=n;i=i+1)
{
cin>>a[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i=i+1)
{
b[i]=min(abs(a[i]-0),abs(l+1-a[i]));
}
sort(b+1,b+n+1);
cout<<b[n]<<" "<<max(abs(a[n]-0),abs(a[1]-l-1));
}
}
P1223 排队接水
1.思路:贪心
2.代码:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int zhi;
int num;
}a[1001];
bool cmp (node a,node b)
{
return a.zhi<b.zhi;
}
int main()
{
int n;
cin>>n;
double tot[n+1];
memset(tot,0,sizeof(tot));
for(int i=1;i<=n;i=i+1)
{
a[i].num=i;
cin>>a[i].zhi;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i=i+1)
{
tot[i]=tot[i-1]+a[i].zhi*(n-i);
if(i==1)
{
cout<<a[i].num;
}
else
{
cout<<" "<<a[i].num;
}
}
cout<<endl;
tot[n]=tot[n]/n;
cout<<fixed<<setprecision(2)<<tot[n];
}
P1803 凌乱的yyy / 线段覆盖
1.思路:贪心,对比赛的结束时间从小到大进行排序
2.代码:
#include <bits/stdc++.h>
using namespace std;
struct bs
{
int a;
int b;
}h[1000005];
bool cmp(bs x, bs y)
{
return x.b<y.b;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i=i+1)
{
cin>>h[i].a>>h[i].b;
}
sort(h+1,h+n+1,cmp);
int qe=h[1].b;
int num1=1;
for(int i=2;i<=n;i=i+1)
{
if(h[i].a>=qe)
{
qe=h[i].b;
num1++;
}
}
cout<<num1;
}
P1031 [NOIP2002 提高组] 均分纸牌
1.思路:当一堆纸牌与平均数不相等时,把欠缺的或多余的部分给下一堆
2.代码:
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main()
{
int n;
cin>>n;
int z=0;
for(int i=1;i<=n;i=i+1)
{
cin>>a[i];
z=z+a[i];
}
int h=z/n;
int num1=0;
for(int i=1;i<=n;i=i+1)
{
a[i]=a[i]-h;
}
for(int i=1;i<n;i=i+1)
{
if(a[i]==0)
{
continue;
}
else
{
a[i+1]=a[i]+a[i+1];
num1++;
}
}
cout<<num1;
}
P1094 [NOIP2007 普及组] 纪念品分组
1.思路:贪心算法,使纪念品中价值最小的和价值最大的归为一组
2.代码:
#include <bits/stdc++.h>
using namespace std;
int a[30005];
int main()
{
int w;
cin>>w;
int n;
cin>>n;
for(int i=1;i<=n;i=i+1)
{
cin>>a[i];
}
sort(a+1,a+n+1);
int r=n;
int l=1;
int num1=0;
while(l<r)
{
if(a[r]+a[l]<=w)
{
num1++;
r--;
l++;
}
else
{
num1++;
r=r-1;
}
}
if(l==r)
{
num1++;
}
cout<<num1;
}
P1080 [NOIP2012 提高组] 国王游戏
1.思路:贪心+高精度算法
贪心:以下是从洛谷题解中复制过来的,自己确实推不出来也想不到这个贪心
如果大臣1放在前面,他俩获得的金币数分别为:
a0/b1,a0*a1/b2
如果大臣2放在前面,他俩获得的金币数分别为:
a0/b2,a0*a2/b1
首先,我们约去式子里面的a0,然后分别讨论两种情况的最大值,就变成了比较:
max(1/b1,a1/b2)和max(1/b2,a2/b1)的大小
根据0<a,a是整数的条件,我们可以得出:
a1/b2 >= 1/b2、1/b1 <= a2/b1
那么,如果1/b1是最大的,则有
1/b1>=a2/b1,只可能左右两边相等,则有1/b2<=a2/b1,所以两种情况的最大值是一样的,则不用交换。
同理可得1/b2是最大的情况也不用交换。
那么我们就只要a1/b2和a2/b1的大小就可以了,也就是说如果a1/b2>a2/b1,那么就要交换,变形得:
a1*b1 > a2*b2
高精度加法:
string add(string str1,string str2)
{
string str;
int len1=str1.length();
int len2=str2.length();
if(len1<len2)
{
for(int i=1;i<=len2-len1;i=i+1)
{
str1="0"+str1;
}
}
else
{
for(int i=1;i<=len1-len2;i=i+1)
{
str2="0"+str2;
}
}
len1=str1.length();
int cf=0;
int temp;
for(int i=len1-1;i>=0;i=i-1)
{
temp=str1[i]-'0'+str2[i]-'0'+cf;
cf=temp/10;
temp%=10;
str=char(temp+'0')+str;
}
if(cf!=0)
{
str=char(cf+'0')+str;
}
return str;
}
高精度乘法(高精乘以高精):
string mul(string str1,string str2)
{
string str;
int len1=str1.length();
int len2=str2.length();
string tempstr;
for(int i=len2-1;i>=0;i--)
{
tempstr="";
int temp=str2[i]-'0';
int t=0;
int cf=0;
if(temp!=0)
{
for(int j=1;j<=len2-1-i;j++)
{
tempstr+="0";
}
for(int j=len1-1;j>=0;j--)
{
t=(temp*(str1[j]-'0')+cf)%10;
cf=(temp*(str1[j]-'0')+cf)/10;
tempstr=char(t+'0')+tempstr;
}
if(cf!=0)
{
tempstr=char(cf+'0')+tempstr;
}
}
str=add(str,tempstr);
}
str.erase(0,str.find_first_not_of('0'));
return str;
}
高精度除法(高精除以低精):
string mult(string a,int b)
{
int i=0,tag=0,la=a.size();int d=0;
string c="";
while(i<=la)
{
if(b>d)
{
d=d*10+a[i++]-'0';
if(tag)c=c+"0";
}
else
{
c=c+char(d/b+'0');
d=d%b;
d=d*10+a[i++]-'0';
tag=1;
}
}
if(tag==0)c=c+"0";
return c;
}
2.代码:暂时只能得到60分,看看这周里能否找出漏洞并进行完善
#include <bits/stdc++.h>
using namespace std;
struct dc
{
string a;
string b;
int sz;
}h[1005];
string add(string str1,string str2)
{
string str;
int len1=str1.length();
int len2=str2.length();
if(len1<len2)
{
for(int i=1;i<=len2-len1;i=i+1)
{
str1="0"+str1;
}
}
else
{
for(int i=1;i<=len1-len2;i=i+1)
{
str2="0"+str2;
}
}
len1=str1.length();
int cf=0;
int temp;
for(int i=len1-1;i>=0;i=i-1)
{
temp=str1[i]-'0'+str2[i]-'0'+cf;
cf=temp/10;
temp%=10;
str=char(temp+'0')+str;
}
if(cf!=0)
{
str=char(cf+'0')+str;
}
return str;
}
string mul(string str1,string str2)
{
string str;
int len1=str1.length();
int len2=str2.length();
string tempstr;
for(int i=len2-1;i>=0;i--)
{
tempstr="";
int temp=str2[i]-'0';
int t=0;
int cf=0;
if(temp!=0)
{
for(int j=1;j<=len2-1-i;j++)
{
tempstr+="0";
}
for(int j=len1-1;j>=0;j--)
{
t=(temp*(str1[j]-'0')+cf)%10;
cf=(temp*(str1[j]-'0')+cf)/10;
tempstr=char(t+'0')+tempstr;
}
if(cf!=0)
{
tempstr=char(cf+'0')+tempstr;
}
}
str=add(str,tempstr);
}
str.erase(0,str.find_first_not_of('0'));
return str;
}
string mult(string a,int b)
{
int i=0,tag=0,la=a.size();int d=0;
string c="";
while(i<=la)
{
if(b>d)
{
d=d*10+a[i++]-'0';
if(tag)c=c+"0";
}
else
{
c=c+char(d/b+'0');
d=d%b;
d=d*10+a[i++]-'0';
tag=1;
}
}
if(tag==0)c=c+"0";
return c;
}
string doit(int a)
{
string b;
while(a>0)
{
b=b+char(a%10+'0');
a/=10;
}
return b;
}
bool zx(string a,string b)
{
if(a.size()<b.size())
{
return 1;
}
else if(a.size()>b.size())
{
return 0;
}
else
{
for(int i=0;i<a.size();i=i+1)
{
if(a[i]>b[i])
{
return 0;
}
else if(a[i]<b[i])
{
return 1;
}
}
}
return 0;
}
bool cmp(dc x,dc y)
{
return zx(mul(x.a,x.b),mul(y.a,y.b));
}
int main()
{
int n;
cin>>n;
string z;
cin>>z;
int x;
cin>>x;
string da="0";
for(int i=1;i<=n;i=i+1)
{
cin>>h[i].a;
cin>>h[i].sz;
h[i].b=doit(h[i].sz);
}
sort(h+1,h+n+1,cmp);
for(int i=1;i<=n;i=i+1)
{
string g=mult(z,h[i].sz);
if(zx(da,g))
{
da=g;
}
z=mul(z,h[i].a);
}
cout<<da;
}
P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
1.思路:优先队列,由于用sort排序的话最大要进行大约20000次的排序,有可能在时间复杂度上无法通过代码,选择优先队列,进行一次插入和删除操作的复杂度为O(logn)
2.关键代码:
priority_queue <int,vector<int>,greater<int> > q;从小到大排序
priority_queue <int> q;默认为从大到小排序
priority_queue<node> q;结构体排序
在结构体内添加排序代码:
friend bool operator <(xx a,xx b)
{
return a.rs<b.rs;
}
3.代码:
#include <bits/stdc++.h>
using namespace std;
int a[10005];
priority_queue <int,vector<int>,greater<int> > q;
int main()
{
int n;
cin>>n;
long long z=0;
for(int i=1;i<=n;i=i+1)
{
int x;
cin>>x;
q.push(x);
}
while(!q.empty())
{
int a=q.top();
q.pop();
int b;
if(q.empty())
{
cout<<z;
break;
}
else
{
b=q.top();
q.pop();
}
z=z+a+b;
q.push(a+b);
}
}
P1199 [NOIP2010 普及组] 三国游戏
1.思路:贪心算法,以四个武将为例画图模拟过程,发现我们能取到的最大武将默契值就是每列第二大的数
2.代码:
#include <bits/stdc++.h>
using namespace std;
int a[505][505];
int b[505];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i=i+1)
{
a[i][i]=0;
}
for(int i=1;i<=n;i=i+1)
{
for(int j=i+1;j<=n;j=j+1)
{
cin>>a[i][j];
a[j][i]=a[i][j];
}
}
int max1=0;
int max2=0;
for(int j=1;j<=n;j=j+1)
{
for(int i=1;i<=n;i=i+1)
{
if(max1<a[j][i])
{
max2=max1;
max1=a[j][i];
}
else if(max2<a[j][i])
{
max2=a[j][i];
}
}
b[j]=max2;
max1=0;
}
sort(b+1,b+n+1);
cout<<1<<endl;
cout<<b[n];
}