A:題意是有n個手機和一個充電寶,問你最多能把幾個手機充滿電(100%)。直接排序嘛,然後一直減就行了。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int t;
cin>>t;
while(t--)
{
int a[111];
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n);
int ans=0;
for(int i=n-1;i>=0;i--)
{
if(m>=100-a[i])
{
ans++;
m-=100-a[i];
}
else break;
}
cout<<ans<<endl;
}
return 0;
}
B:就是判斷兩個圓之間有幾個切線,相離4條,相切3條,相交2條,內切1條,內含0條,如果兩圓相同就輸出-1。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int t;
cin>>t;
while(t--)
{
int x1,y1,r1,x2,y2,r2;
cin>>x1>>y1>>r1>>x2>>y2>>r2;
int dy=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
int dr=(r1-r2)*(r1-r2);
int drh=(r1+r2)*(r1+r2);
if(dy<dr)
{
cout<<"0"<<endl;
}
else if(dy==dr&&dr!=0)
{
cout<<"1"<<endl;
}
else if(dy==0&&r1==r2)
{
cout<<"-1"<<endl;
}
else if(dy==drh)
{
cout<<"3"<<endl;
}
else if(dy>drh)
{
cout<<"4"<<endl;
}
else cout<<"2"<<endl;
}
return 0;
}
C:01揹包,根據數據範圍可以知道是以價值總和做揹包容量的。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define LL long long int
const int inf=0x3f3f3f3f;
LL dp[5050];
int w[550];
int v[550];
int main()
{
int T;
int n,b;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&b);
int sum=0;
for(int i=0;i<n;i++)
{
cin>>w[i]>>v[i];
sum+=v[i];
}
memset(dp,inf,sizeof(dp));
dp[0]=0;
for(int i=0;i<n;i++)
{
for(int j=sum;j>=v[i];j--)
{
dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
}
}
for(int i=sum;i>=0;i--)
{
if(dp[i]<=b)
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
E:讀錯題目了,讓我寫了好大一會的最長上升子序列。。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long int
int T;
int n, m, a;
int vis[100100];
int pre[100100];
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
int cmp = 0;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++)
{
scanf("%d", &a);
if (!a)
cmp++;
else
vis[a] = 1;
}
memset(pre, 0, sizeof(pre));
for (int i = 1; i <= m; i++)
pre[i] = pre[i - 1] + (!vis[i]);
int res = 0;
for (int i = 1; i <= m; i++)
{
int cnt = upper_bound(pre + i, pre + m + 1, cmp + pre[i-1]) - pre;
res = max(cnt - i, res);
}
printf("%d\n", res);
}
return 0;
}
H:很巧妙的一個算法,隊友寫的。我現在也只是模糊的懂了,等下再仔細看看。用了一個二叉樹的思想,實現的話就是用優先隊列每次先取次小的(因爲最小的時間會被覆蓋掉的)加上工人繁殖(?)的時間,這樣雖然處理是從小往大處理,但是實際上的意思是每次先讓工人去修耗時最長的房子。越到後面的話,修建房子的時間就越短,但是相應的繁殖耗時就越長。(這道題優先隊列裏面可以直接多寫一點東西讓從小到大輸出的,不用在結構體裏面重載的)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
struct node
{
int t;
bool operator < (const node & a) const
{
return t>a.t;
}
};
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m,k;
priority_queue <node> q;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++)
{
node a;
scanf("%d",&a.t);
q.push(a);
}
while(n>m)
{
q.pop();
node a=q.top();
a.t+=k;
q.push(a);
q.pop();
n--;
}
while(q.size()!=1)q.pop();
cout<<q.top().t<<endl;
}
return 0;
}
J:又是隊友的代碼。。我自己寫的不對。。我剛開始寫了大於等於第二個的1.5倍就能贏,結果wa了兩發。後來隊友貌似算法對但是一直沒過,最後發現這個oj的輸入long long int 只能用I64d不能用lld,血崩。等下看完再來說思路。
看了隊友的代碼發現寫的有點麻煩的,自己寫了一發。思路就是把前面的除以三,如果有餘數就平分到其中任意一個或兩個,然後取最小的兩個相加再加上2得到一個值,如果後面的值大於等於這個值,就會輸,不然的話就穩贏。(證明略,很簡單的,自己玩一下就行了)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long int
int main()
{
int T;
int a, b;
cin >> T;
while (T--)
{
scanf("%d%d", &a, &b);
int cmp = a % 3;
int aa = a / 3;
int bb = a / 3;
if (cmp == 2)
aa++;
if (aa + bb + 2 <= b)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}