第六屆浙江省賽題解
A. Second-price Auction
題目大意
有n個投標者,投標最高的獲得物品,需要支付第二投標者的價格.
解題思路
使用結構體,保存投標的價格和一開始的排序.
然後根據投標價格排序,使用sort就可以了
AC代碼
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 110;
struct node
{
int n, w;
}a[maxn];
bool cmp (node a, node b){
if(a.w != b.w)
return a.w < b.w;
else
return a.n > b.n;
}
int main()
{
int T;
int n;
cin >> T;
while(T--)
{
memset(a, 0 ,sizeof(a));
cin >> n;
for(int i=1; i<=n; i++){
cin >> a[i].w;
a[i].n = i;
}
sort(a+1, a+n+1, cmp);
cout << a[n].n << ' ' << a[n-1].w << endl;
}
return 0;
}
B.Light Bulb
題目大意
給你 , , ,求陰影部分 的最大長度
解題思路
因爲 , ,是固定的長度的,首先延長邊,根據邊的比例能夠退出x+y的函數表達式(用θ表示)
列出兩個極端的情況,人在最左邊和最右邊,這就是θ的取值範圍,然後對上面的函數表達式求導,得到函數是先增後減的,有極大值
求出零點θ的值(二分),然後判斷3點的值的最值即可
AC代碼
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
double H,D,h;
double mid;
bool judge(double mid) {
double Sin = sin(mid);
Sin = Sin * Sin;
double Cos = 1.0-Sin;
double ans = D/Sin - (H-h)/Cos;
if(ans < 0) return false;
return true;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%lf%lf%lf",&H,&h,&D);
double l = atan(D/H), r = atan(D/(H-h));
for(int i=0; i<1000; i++) {
mid = (l+r)/2.0;
if(judge(mid))
l = mid;
else r = mid;
}
double ans = max( (D*h/H), h);
double tanx = H - (D/tan(mid)) + (tan(mid)*(h-H)) + D;
ans = max(ans, tanx);
printf("%.3f\n", ans);
}
return 0;
}
C.Connect them
題目大意
有 臺計算機,要建立小型局域網,所有連接都是雙向的。兩臺計算機的鏈接成本是 ,找到最小的成本的連接方法
解題思路
一個最小生成樹的模板題目。但是他要輸出最小的字典序。
最簡單的方法是輸出邊的時候排序。
但是,如果生成樹不是一條的話就很難弄了。
所以我們可以吧輸入的數據,先排序,首先根據費用排序,然後根據起點排序,最後根據終點排序。
AC代碼
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10000+10;
struct Node{
int s,e;
int sum;
}node[maxn];
struct MP{
int x,y;
}mp[maxn];
bool cmd1(MP a,MP b){
if(a.x == b.x) return a.y < b.y;
else return a.x<b.x;
}
bool cmd(Node a,Node b){
if(a.sum != b.sum) return a.sum < b.sum;
if(a.s != b.s) return a.s < b.s;
return a.e < b.e;
}
int pre[maxn];
int p=0,n,pp=0;
int Find(int root){
return pre[root]==root?root:Find(pre[root]);
}
int kruskal() {
int ans = 0;
for(int i = 1; i <=n ; i++) pre[i] = i;
sort(node,node+p,cmd);
pp = 0;
for(int i = 0; i < p; i++) {
int x = Find(node[i].s);
int y = Find(node[i].e);
if(x != y) {
mp[pp].x = node[i].s;
mp[pp++].y = node[i].e;
ans ++;
pre[y] = x;
}
}
return ans;
}
int main(){
int t;
while(~scanf("%d",&t)){
while(t--){
scanf("%d",&n);
p = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;
scanf("%d",&x);
if(x!=0){
node[p].s = i;
node[p].e = j;
node[p++].sum = x;
}
}
}
int q = kruskal();
if(q == 0 || q != n-1){
printf("-1\n");
}else{
sort(mp,mp+pp,cmd1);
for(int i=0;i<pp;i++){
printf("%d %d%c",mp[i].x,mp[i].y,i==pp-1?'\n':' ');
}
}
}
}
return 0;
}
F.80ers’ Memory
題目大意
看輸入輸出就可以看出.問每個人有幾個關鍵字在典型的80年代關鍵詞中
題解思路
使用map直接存儲字符串,然後直接找就好了
AC代碼
#include<cstdio>
#include<algorithm>
#include<map>
#include<string>
#include<iostream>
using namespace std;
map<string,int> mp;
int main(){
int t;
scanf("%d",&t);
string s;
for(int i=0;i<t;i++){
cin>>s;
mp[s] = 1;
}
int n,p;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&p);
int sum=0;
for(int j=0;j<p;j++){
cin>>s;
if(mp[s]==1) sum++;
}
printf("%d\n",sum);
}
return 0;
}
I.A Stack or A Queue?
題目大意
給你一個輸入序列一個輸出序列,問是queue還是stack,還是都不或者都不是
解題思路
直接模擬,拿輸出序列和queue還有stack輸出對比
AC代碼
#include<cstdio>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
const int maxn = 100+10;
int a[maxn],b[maxn];
queue<int> q;
stack<int> s;
int main(){
int t;
while(~scanf("%d",&t)){
while(t--){
while(!q.empty()) q.pop();
while(!s.empty()) s.pop();
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
q.push(x);
s.push(x);
}
int flag1,flag2;
flag1=flag2=1;
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
if(x==q.front()){
q.pop();
}else{
flag1=0;
}
if(x==s.top()){
s.pop();
}else{
flag2=0;
}
}
if(flag1==1 && flag2==1){
printf("both\n");
}else if(flag1==1 && flag2==0){
printf("queue\n");
}else if(flag1==0 && flag2 == 1){
printf("stack\n");
}else{
printf("neither\n");
}
}
}
return 0;
}
K.K-Nice
題目大意
構造出一個點的值等於周圍四個點的值的和(注:一定是四個點,挨着邊的都不算
解題思路
構造題一般都不是一個解,只要符合題目就行。
因爲一個點的值等於周圍四個點的值的和,所以當都是0時也是符合條件的,題目的樣例中也給出了這種情況,這種也是最好構造的.
我們可以從上到下,除了邊上點,其餘的符合條件的地方使用0,後面不符合條件的用1來填充。
注意最後的空格和換行,不然會WA
AC代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 17;
int num[maxn][maxn];
void tian(int n, int m, int k)
{
if(m < 3){
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
num[i][j] = 0;
}
}
}
else{
int number = k/(m-2);
int i;
for(i=1; i<=number+1; i++){
for(int j=0; j<m; j++){
num[i][j] = 0;
}
}
if(k % (m-2) != 0){
for(int j=0; j<= (k%(m-2)); j++){
num[i][j] = 0;
}
for(int j=(k%(m-2))+1; j < m; j++){
num[i][j] = 1;
}
i++;
}
for(;i < n; i++){
for(int j=0; j<m; j++){
num[i][j] = 1;
}
}
}
}
int main()
{
int T;
int n, m , k;
scanf("%d", &T);
while(T--)
{
scanf("%d %d %d", &n, &m, &k);
tian(n, m, k);
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
printf("%d%c", num[i][j],j==m-1?'\n':' ');
}
}
}
return 0;
}