第六屆福建省賽

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:讀錯題目了,讓我寫了好大一會的最長上升子序列。。
(賽後清題)輸入時先記錄0的數量,用一個數組記錄當前位置之前有多少空位。然後從前往後遍歷位置,得到當前位置到最後位置之前能用0連接起來(覆蓋)的空位長度,從中取最長的長度即可。

#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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章