2019天梯賽第四次訓練賽


7-1 表達式轉換 (25 分)

算術表達式有前綴表示法、中綴表示法和后綴表示法等形式。日常使用的算術表達式是采用中綴表示法,即二元運算符位於兩個運算數中間。請設計程序將中綴表達式轉換為后綴表達式。

輸入格式:

輸入在一行中給出不含空格的中綴表達式,可包含+-*\以及左右括號(),表達式不超過20個字符。

輸出格式:

在一行中輸出轉換后的后綴表達式,要求不同對象(運算數、運算符號)之間以空格分隔,但結尾不得有多余空格。

輸入樣例:

2+3*(7-4)+8/4

輸出樣例:

2 3 7 4 - * + 8 4 / +

這種特判題還是不太熟練,回去反省,需要考慮+2,-3,1.5

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     char s[25],a[25];
 7     scanf("%s",a);
 8     int l=strlen(a),f=0,c=0;
 9     map<char,int>p;//判斷運算符優先級
10     p['+']=p['-']=1;
11     p['*']=p['/']=2;
12     p['(']=p[')']=3;
13     for(int i=0;i<l;i++)
14     {
15         if((i<1||a[i-1]=='(')&&(a[i]=='+'||a[i]=='-')||a[i]=='.'||a[i]>='0'&&a[i]<='9')
16         {
17             if(f++)printf(" ");
18             if(a[i]!='+')printf("%c",a[i]);//(+2-3) -3+7
19             while(a[i+1]=='.'||a[i+1]>='0'&&a[i+1]<='9')i++,printf("%c",a[i]);
20         }
21         else
22         {
23             if(a[i]==')')
24             {
25                 while(c&&s[c-1]!='(')printf(" %c",s[c-1]),c--;
26                 c--;
27             }
28             else if(!c||p[a[i]]>p[s[c-1]])s[c++]=a[i];
29             else
30             {
31                 while(c&&s[c-1]!='(')printf(" %c",s[c-1]),c--;
32                 s[c++]=a[i];
33             }
34         }
35     }
36     while(c)printf(" %c",s[c-1]),c--;
37     return 0;
38 }
7-2 裝箱問題 (20 分)
假設有 N項物品,大小分別為s1,s2....si....sn,其中si為滿足0<=si<=100的整數。要把這些物品裝入到容量為100的一批箱子(序號1-N)中。裝箱方法是:對每項物品, 順序掃描箱子,把該物品放入足以能夠容下它的第一個箱子中。請寫一個程序模擬這種裝箱過程,並輸出每個物品所在的箱子序號,以及放置全部物品所需的箱子數目。

輸入格式:

輸入第一行給出物品個數N(<=1000);第二行給出N個正整數si(0<=si<=100,表示第i項物品的大小)。

輸入樣例:

8
60 70 80 90 30 40 10 20

輸出樣例:

60 1
70 2
80 3
90 4
30 1
40 5
10 1
20 2
5

按題意模擬

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n;
 7     cin>>n;
 8     int a[1005],s[1005];
 9     for(int i=1;i<=n;i++)cin>>a[i],s[i]=0;
10     int go[1005],p=0;
11     for(int i=1;i<=n;i++)
12     {
13         for(int j=1;j<=n;j++)
14         {
15             if(s[j]+a[i]<=100)
16             {
17                 p=max(p,j);
18                 go[i]=j;
19                 s[j]+=a[i];
20                 break;
21             }
22         }
23     }
24     for(int i=1;i<=n;i++)
25         printf("%d %d\n",a[i],go[i]);
26     printf("%d\n",p);
27     return 0;
28 }
7-3 公路村村通 (30 分)

現有村落間道路的統計數據表中,列出了有可能建設成標准公路的若干條道路的成本,求使每個村落都有公路連通所需要的最低成本。

輸入格式:

輸入數據包括城鎮數目正整數N<=1000)和候選道路數目M<=3N);隨后的M行對應M條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。為簡單起見,城鎮從1到N編號。

輸出格式:

輸出村村通需要的最低成本。如果輸入數據不足以保證暢通,則輸出1,表示需要建設更多公路。

輸入樣例:

6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

輸出樣例:

12

最小生成樹模板

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct edge
 5 {
 6     int u,v,w; 
 7 }e[3005];
 8 bool cmp(edge a,edge b)
 9 {
10     return a.w<b.w;
11 }
12 int f[3005];
13 int find(int x)
14 {
15     return f[x]==x?x:f[x]=find(f[x]);
16 }
17 int n,m;
18 int kru()
19 {
20     sort(e,e+m,cmp);
21     int ans=0,cnt=0;
22     for(int i=0;i<m;i++)
23     {
24         int fu=find(e[i].u);
25         int fv=find(e[i].v);
26         if(fu!=fv)
27         {
28             f[fu]=fv;
29             ans+=e[i].w;
30             if(++cnt==n-1)break;
31         }
32     }
33     if(cnt<n-1)return -1;
34     return ans;
35 }
36 int main()
37 {
38     cin>>n>>m;
39     for(int i=1;i<=n;i++)f[i]=i;
40     for(int i=0;i<m;i++)
41         scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
42     printf("%d\n",kru());
43 }
7-4 修理牧場 (25 分)
農夫要修理牧場的一段柵欄,他測量了柵欄,發現需要 N塊木頭,每塊木頭長度為整數L i個長度單位,於是他購買了一條很長的、能鋸成 N塊的木頭,即該木頭的長度是L i的總和。
但是農夫自己沒有鋸子,請人鋸木的酬金跟這段木頭的長度成正比。為簡單起見,不妨就設酬金等於所鋸木頭的長度。例如,要將長度為20的木頭鋸成長度為8、7和5的三段,第一次鋸木頭花費20,將木頭鋸成12和8;第二次鋸木頭花費12,將長度為12的木頭鋸成7和5,總花費為32。如果第一次將木頭鋸成15和5,則第二次鋸木頭花費15,總花費為35(大於32)。

請編寫程序幫助農夫計算將木頭鋸成N塊的最少花費。

輸入格式:

輸入首先給出正整數N(<=104),表示要將木頭鋸成N塊。第二行給出N個正整數(<=50),表示每段木塊的長度。N個正整數(50),表示每段木塊的長度。

輸出格式:

輸出一個整數,即將木頭鋸成N塊的最少花費。

輸入樣例:

8
4 5 1 2 1 3 1 1

輸出樣例:

49

每次取最小兩個合並

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n;
 7     cin>>n;
 8     priority_queue< int,vector<int>,greater<int> >q;
 9     for(int i=0;i<n;i++)
10     {
11         int x;
12         cin>>x;
13         q.push(x);
14     }
15     int sum=0;
16     while(q.size()>=2)
17     {
18         int a=q.top();
19         q.pop();
20         int b=q.top();
21         q.pop();
22         sum+=a+b;
23         q.push(a+b);
24     }
25     printf("%d\n",sum);
26     return 0;
27 }
7-5 特殊堆棧 (30 分)

堆棧是一種經典的后進先出的線性結構,相關的操作主要有“入棧”(在堆棧頂插入一個元素)和“出棧”(將棧頂元素返回並從堆棧中刪除)。本題要求你實現另一個附加的操作:“取中值”——即返回所有堆棧中元素鍵值的中值。給定 N 個元素,如果 N 是偶數,則中值定義為第 N/2 小元;若是奇數,則為第 (N+1)/2 小元。

輸入格式:

輸入的第一行是正整數 N(<=105)。隨后 N 行,每行給出一句指令,為以下 3 種之一:

Push key
Pop
PeekMedian

其中 key 是不超過105的正整數;Push 表示“入棧”;Pop 表示“出棧”;PeekMedian 表示“取中值”。​​ 的正整數Push 表示“入棧”;Pop 表示“出棧”;PeekMedian 表示“取中

對每個 Push 操作,將 key 插入堆棧,無需輸出;對每個 PopPeekMedian 操作,在一行中輸出相應的返回值。若操作非法,則對應輸出 Invalid

輸入樣例:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

輸出樣例:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

pop和push操作直接用棧操作

由於N很大,中位數如果用數組移位插入刪除會超時O(n),可以考慮二分[0,100000]然后用樹狀數組判斷前面有幾個比他小O(lognlogn)

總復雜度O(nlognlogn),有人說O(n^2)可以過,orz

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=1e5+5;
 5 int n=100000;
 6 stack<int>st;
 7 struct BIT{
 8     int sum[N];
 9     void init(){memset(sum,0,sizeof(sum));}
10     int lowbit(int x){return x&(-x);}
11     void update(int x,int w){for(int i=x;i<=n;i+=lowbit(i))sum[i]+=w;}
12     int query(int x){int ans=0;for(int i=x;i>0;i-=lowbit(i))ans+=sum[i];return ans;}
13 }T;
14 int main()
15 {
16     T.init();
17     int q;
18     char op[25];
19     scanf("%d",&q);
20     for(int i=1;i<=q;i++)
21     {
22         scanf("%s",op);
23         if(op[1]=='o')
24         {
25             if(st.empty())printf("Invalid\n");
26             else printf("%d\n",st.top()),T.update(st.top(),-1),st.pop();
27         }
28         else if(op[1]=='u')
29         {
30             int key;
31             scanf("%d",&key);
32             st.push(key);
33             T.update(key,1);
34         }
35         else
36         {
37             int cnt=((int)st.size()+1)/2;
38             if(cnt==0)
39             {
40                 printf("Invalid\n");
41                 continue;
42             }
43             int L=0,R=100000;
44             while(L<R)
45             {
46                 int mid=(L+R)>>1;
47                 if(T.query(mid)>=cnt)R=mid;
48                 else L=mid+1;
49             }
50             printf("%d\n",R);
51         }
52     }
53     return 0;
54 }
7-6 社交集群 (30 分)

當你在社交網絡平台注冊時,一般總是被要求填寫你的個人興趣愛好,以便找到具有相同興趣愛好的潛在的朋友。一個“社交集群”是指部分興趣愛好相同的人的集合。你需要找出所有的社交集群。

輸入格式:

輸入在第一行給出一個正整數 N(<=1000),為社交網絡平台注冊的所有用戶的人數。於是這些人從 1 到 N 編號。隨后 N 行,每行按以下格式給出一個人的興趣愛好列表:

Ki:hi[1]hi[2]...hi[Ki]

其中ki>0是興趣愛好的個數,hi[j]是第j個興趣愛好的編號,為區間 [1, 1000] 內的整數。

輸出格式:

首先在一行中輸出不同的社交集群的個數。隨后第二行按非增序輸出每個集群中的人數。數字間以一個空格分隔,行末不得有多余空格。

輸入樣例:

8
3: 2 7 10
1: 4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4

輸出樣例:

3
4 3 1

並查集,1-1000是興趣的編號,1001-1000+n是人的編號

然后就是並查集模板了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=2005;
 5 int f[N];
 6 int find(int x)
 7 {
 8     return f[x]==x?x:f[x]=find(f[x]);
 9 }
10 int main()
11 {
12     int n,k,like;
13     cin>>n;
14     for(int i=1;i<=2000;i++)f[i]=i;
15     for(int i=1;i<=n;i++)
16     {
17         scanf("%d:",&k);
18         for(int j=1;j<=k;j++)
19         {
20             scanf("%d",&like);
21             f[find(like)]=f[find(i+1000)];
22         }
23     }
24     bool vis[2005]={0};
25     int cnt=0;
26     int sum[2005]={0};
27     for(int i=1001;i<=1000+n;i++)
28     {
29         if(vis[i])continue;
30         int fa=f[find(i)];
31         for(int j=i;j<=1000+n;j++)
32         {
33             if(fa==f[find(j)])
34             {
35                 sum[cnt]++;
36                 vis[j]=true;
37             }
38         }
39         cnt++;
40     }
41     printf("%d\n",cnt);
42     sort(sum,sum+cnt);
43     for(int i=cnt-1;i>=0;i--)
44         printf("%d%c",sum[i],i==0?'\n':' ');
45     return 0;
46 }
7-7 抓老鼠啊~虧了還是賺了? (20 分)

某地老鼠成災,現懸賞抓老鼠,每抓到一只獎勵10元,於是開始跟老鼠斗智斗勇:每天在牆角可選擇以下三個操作:放置一個帶有一塊奶酪的捕鼠夾(T),或者放置一塊奶酪(C),或者什么也不放(X)。捕鼠夾可重復利用,不計成本,奶酪每塊3元。聰明的老鼠呢?它們每天可能會派出一只老鼠到牆角,看看牆角有啥:

  • 若什么也沒有(X),老鼠們就不高興了(Unhappy),會有長達一天(也就是第二天)的不高興期。在不高興期間,不派出老鼠。不高興期結束之后,派出老鼠。
  • 若有捕鼠夾(T),這只老鼠被引誘吃掉奶酪並被打死(Dead),老鼠們會有長達兩天(也就是第二和第三天)的傷心期。在傷心期間,不派出老鼠。傷心期結束之后,派出老鼠。在這種情況下,抓到1只老鼠可獲得獎勵10元,但同時也耗費了一塊奶酪。注意,如果某一天放置了捕鼠夾但老鼠沒有出現,則沒有耗費奶酪。
  • 若有奶酪(C),老鼠吃了奶酪會很開心(Happy!),會有長達兩天(第二和第三天)的興奮期。在興奮期間,即使疊加了不高興或者傷心,也必定派出老鼠。在這種情況下,沒抓到老鼠,而且耗費了一塊奶酪。注意,如果某一天放置了奶酪但老鼠沒有出現,則奶酪可以下次再用,沒有耗費。

現在給你連續幾天的操作序列,且已知第一天肯定會派出老鼠,請判斷老鼠每天的狀態,並計算盈利。

輸入格式:

輸入在一行中給出連續的由CTX組成的不超過70個字符的字符串,以$結束。字符串中每個字符表示這一天的操作( 即X:什么都不放;T:放捕鼠夾;C:放奶酪)。題目保證至少有一天的操作輸入。

輸出格式:

要求在第一行輸出連續的字符串,與輸入相對應,給出老鼠的狀態:

  • ! 表示派出老鼠吃到奶酪
  • D 表示派出老鼠被打死
  • U 表示派出老鼠無所獲
  • - 表示沒有派出老鼠

第二行則應輸出一個整數表示盈利。(如果有虧損,則是負數)

輸入樣例1:

TXXXXC$

輸出樣例1:

D--U-! 
4

輸入樣例2:

CTTCCX$

輸出樣例2:

!DD--U 
11

按題意模擬,水平不好代碼有點長

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     string s;
 7     cin>>s;
 8     int cost=0,happy=0,unhappy=0;
 9     for(int i=0;i<s.size();i++)
10     {
11         if(s[i]=='$')break;
12         if(s[i]=='X')
13         {
14             if(happy>0||(happy==0&&unhappy==0))//派出
15             {
16                 printf("U");
17                 if(happy>0)happy--;
18                 unhappy=-1;
19             }
20             else//未派出
21             {
22                 if(unhappy<0)unhappy++;
23                 if(happy<0)happy++;
24                 printf("-");
25             }
26         }
27         if(s[i]=='T')
28         {
29             if(happy>0||(happy==0&&unhappy==0))
30             {
31                 cost-=3;
32                 printf("D");//抓到
33                 if(happy>0)happy--;
34                 unhappy=-2;
35                 cost+=10;
36             }
37             else
38             {
39                 if(unhappy<0)unhappy++;
40                 if(happy<0)happy++;
41                 printf("-");
42             }
43         }
44         if(s[i]=='C')
45         {
46             if(happy>0||(happy==0&&unhappy==0))
47             {
48                 printf("!");//吃到奶酪
49                 happy=2;
50                 if(unhappy<0)unhappy++;
51                 cost-=3;
52             }
53             else
54             {
55                 if(unhappy<0)unhappy++;
56                 if(happy<0)happy++;
57                 printf("-");
58             }
59         }
60     }
61     printf("\n%d",cost);
62     return 0;
63 }
7-8 逆散列問題 (30 分)
給定長度為N的散列表,處理整數最常用的散列映射是H(x)= x%N 。如果我們決定用線性探測解決沖突問題,則給定一個順序輸入的整數序列后,我們可以很容易得到這些整數在散列表中的分布。例如我們將 1、2、3 順序插入長度為 3 的散列表HT[]后,將得到HT[0]=3HT[1]=1HT[2]=2的結果。

但是現在要求解決的是“逆散列問題”,即給定整數在散列表中的分布,問這些整數是按什么順序插入的?

輸入格式:

輸入的第一行是正整數 N(<=1000),為散列表的長度。第二行給出了 N 個整數,其間用空格分隔,每個整數在序列中的位置(第一個數位置為0)即是其在散列表中的位置,其中負數表示表中該位置沒有元素。題目保證表中的非負整數是各不相同的。

輸出格式:

按照插入的順序輸出這些整數,其間用空格分隔,行首尾不能有多余的空格。注意:對應同一種分布結果,插入順序有可能不唯一。例如按照順序 3、2、1 插入長度為 3 的散列表,我們會得到跟 1、2、3 順序插入一樣的結果。在此規定:當前的插入有多種選擇時,必須選擇最小的數字,這樣就保證了最終輸出結果的唯一性。

輸入樣例:

11
33 1 13 12 34 38 27 22 32 -1 21

輸出樣例:

1 13 12 21 33 34 38 27 22 32

直接莽了個暴力,果然出奇跡

首先需要知道線性探測就是如果a[i]%n產生沖突就往后去找空的填(離散課)

然后就是把可以填的都找到,然后輸出個最小的

O(n^3)~ 1e9嗯10ms

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,a[1005],has[1005];
 5 bool vis[1005];
 6 bool check(int h,int ok)
 7 {
 8     for(int i=0;(h+i)%n!=ok&&i<n;i++)
 9         if(vis[(h+i)%n]==false)
10             return false;
11     return !vis[ok];
12 }
13 int main()
14 {
15     int c=0;
16     scanf("%d",&n);
17     for(int i=0;i<n;i++)
18     {
19         scanf("%d",&a[i]);
20         has[i]=a[i]%n;
21         if(a[i]>=0)c++;
22     }
23     int ok[1005],ac[1005],pac=0;
24     while(pac<c)
25     {
26         int p=0,minn=1e9,xb=0;
27         for(int i=0;i<n;i++)
28         {
29             if(a[i]==-1||vis[i])continue;
30             if(check(has[i],i))
31             {
32                 if(minn>a[i])
33                 {
34                     minn=a[i];
35                     xb=i;
36                 }
37             }
38         }
39         ac[pac++]=minn;
40         vis[xb]=true;
41     }
42     for(int i=0;i<pac;i++)
43         printf("%d%c",ac[i],i==pac-1?'\n':' ');
44     return 0;
45 }
7-9 BCD解密 (10 分)

BCD數是用一個字節來表達兩位十進制的數,每四個比特表示一位。所以如果一個BCD數的十六進制是0x12,它表達的就是十進制的12。但是小明沒學過BCD,把所有的BCD數都當作二進制數轉換成十進制輸出了。於是BCD的0x12被輸出成了十進制的18了!

現在,你的程序要讀入這個錯誤的十進制數,然后輸出正確的十進制數。提示:你可以把18轉換回0x12,然后再轉換回12。

輸入格式:

輸入在一行中給出一個[0, 153]范圍內的正整數,保證能轉換回有效的BCD數,也就是說這個整數轉換成十六進制時不會出現A-F的數字。

輸出格式:

輸出對應的十進制數。

輸入樣例:

18

輸出樣例:

12

水題

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6        int n;
 7        cin>>n;
 8        cout<<n/16*10+n%16;
 9     return 0;
10 }
7-10 整數四則運算 (10 分)

本題要求編寫程序,計算2個正整數的和、差、積、商並輸出。題目保證輸入和輸出全部在整型范圍內。

輸入格式:

輸入在一行中給出2個正整數A和B。

輸出格式:

在4行中按照格式“A 運算符 B = 結果”順序輸出和、差、積、商。

輸入樣例:

3 2

輸出樣例:

3 + 2 = 5
3 - 2 = 1
3 * 2 = 6
3 / 2 = 1

水題

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int a,b;
 7     cin>>a>>b;
 8     printf("%d + %d = %d\n",a,b,a+b);
 9     printf("%d - %d = %d\n",a,b,a-b);
10     printf("%d * %d = %d\n",a,b,a*b);
11     printf("%d / %d = %d\n",a,b,a/b);
12     return 0;
13 }
7-11 兔子繁衍問題 (15 分)

一對兔子,從出生后第3個月起每個月都生一對兔子。小兔子長到第3個月后每個月又生一對兔子。假如兔子都不死,請問第1個月出生的一對兔子,至少需要繁衍到第幾個月時兔子總數才可以達到N對?

輸入格式:

輸入在一行中給出一個不超過10000的正整數N。

輸出格式:

在一行中輸出兔子總數達到N最少需要的月數。

輸入樣例:

30

輸出樣例:

9

dp[i]表示第i天有多少對兔子

顯然dp[i]=dp[i-1]+dp[i-2](昨天的+新出生的)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n;
 7     cin>>n;
 8     int dp[22]={0};
 9     dp[1]=1;
10     dp[2]=1;
11     if(n==1)printf("%d\n",1);
12     else
13     {
14         for(int i=3;i<=21;i++)
15         {
16             dp[i]=dp[i-1]+dp[i-2];
17             if(dp[i]>=n)
18             {
19                 printf("%d\n",i);
20                 break;
21             }
22         }
23     }
24     return 0;
25 }
7-12 復數四則運算 (15 分)

本題要求編寫程序,計算2個復數的和、差、積、商。

輸入格式:

輸入在一行中按照a1 b1 a2 b2的格式給出2個復數C1=a1+b1i和C2=a2+b2i的實部和虛部。題目保證C2不為0。

輸出格式:

分別在4行中按照(a1+b1i) 運算符 (a2+b2i) = 結果的格式順序輸出2個復數的和、差、積、商,數字精確到小數點后1位。如果結果的實部或者虛部為0,則不輸出。如果結果為0,則輸出0.0。

輸入樣例1:

2 3.08 -2.04 5.06

輸出樣例1:

(2.0+3.1i) + (-2.0+5.1i) = 8.1i
(2.0+3.1i) - (-2.0+5.1i) = 4.0-2.0i
(2.0+3.1i) * (-2.0+5.1i) = -19.7+3.8i
(2.0+3.1i) / (-2.0+5.1i) = 0.4-0.6i

輸入樣例2:

1 1 -1 1.01

輸出樣例2:

(1.0+1.0i) + (-1.0+1.0i) = 0.0
(1.0+1.0i) - (-1.0+1.0i) = 2.0+2.0i
(1.0+1.0i) * (-1.0+1.0i) = -2.0i
(1.0+1.0i) / (-1.0+1.0i) = -1.0

大模擬,輸出比較麻煩,這個精度誤差EPS=0.1才可以過(跪了),除法考慮上下同乘共軛復數

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 double a1,b1,a2,b2;
 5 void w(double a,char c,double b)
 6 {
 7     //輸出前面的
 8     if(b1>=0&&b2>=0)printf("(%.1lf+%.1lfi) %c (%.1lf+%.1lfi) = ",a1,b1,c,a2,b2);
 9     else if(b1>=0&&b2<0)printf("(%.1lf+%.1lfi) %c (%.1lf%.1lfi) = ",a1,b1,c,a2,b2);
10     else if(b1<0&&b2>=0)printf("(%.1lf%.1lfi) %c (%.1lf+%.1lfi) = ",a1,b1,c,a2,b2);
11     else printf("(%.1lf%.1lfi) %c (%.1lf%.1lfi) = ",a1,b1,c,a2,b2);
12     if(fabs(a)<=1e-1&&fabs(b)<1e-1)
13     {
14         printf("0.0\n");
15         return;
16     }
17     bool ok=0;           
18     if(fabs(a)>1e-1)//a!=0
19     {
20         printf("%.1lf", a);
21         ok=1;
22     }
23     if(fabs(b)>1e-1)//b!=0
24     {
25         if(b>0&&ok)printf("+%.1lfi",b);
26         else printf("%.1lfi",b);
27     }
28     printf("\n");
29 }
30 int main()
31 {
32     scanf("%lf%lf%lf%lf",&a1,&b1,&a2,&b2);
33     double a,b;
34     // +
35     a=a1+a2,b=b1+b2;
36     w(a,'+',b);
37     // -
38     a=a1-a2,b=b1-b2;
39     w(a,'-',b);
40     // *
41     a=a1*a2-b1*b2;
42     b=a1*b2+a2*b1;
43     w(a,'*',b);
44     // /
45     a=(a1*a2+b1*b2)/(a2*a2+b2*b2);
46     b=(a2*b1-a1*b2)/(a2*a2+b2*b2);
47     w(a,'/',b);
48     return 0;
49 }
7-13 計算攝氏溫度 (5 分)

本題要求編寫程序,計算華氏溫度100°F對應的攝氏溫度。計算公式:C = 5 *(F-100)/9,式中:C表示攝氏溫度,F表示華氏溫度,輸出數據要求為整型。

輸入格式:

本題目沒有輸入。

輸出格式:

按照下列格式輸出

fahr = 100, celsius = 計算所得攝氏溫度的整數值

通過計算得到C=37.7輸出37即可,一開始輸出了38(emmm)

1 #include<bits/stdc++.h>
2 using namespace std;
3 
4 int main()
5 {
6     printf("fahr = 100, celsius = 37");
7     return 0;
8 }
7-14 表格輸出 (5 分)

本題要求編寫程序,按照規定格式輸出表格。

輸入格式:

本題目沒有輸入。

輸出格式:

要求嚴格按照給出的格式輸出下列表格:

------------------------------------
Province      Area(km2)   Pop.(10K)
------------------------------------
Anhui         139600.00   6461.00
Beijing        16410.54   1180.70
Chongqing      82400.00   3144.23
Shanghai        6340.50   1360.26
Zhejiang      101800.00   4894.00
------------------------------------

水題

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     printf("------------------------------------\n");
 7     printf("Province      Area(km2)   Pop.(10K)\n");
 8     printf("------------------------------------\n");
 9     printf("Anhui         139600.00   6461.00\n");
10     printf("Beijing        16410.54   1180.70\n");
11     printf("Chongqing      82400.00   3144.23\n");
12     printf("Shanghai        6340.50   1360.26\n");
13     printf("Zhejiang      101800.00   4894.00\n");
14     printf("------------------------------------\n");
15     return 0;
16 }
7-15 水果忍者 (30 分)

2010年風靡全球的“水果忍者”游戲,想必大家肯定都玩過吧?(沒玩過也沒關系啦~)在游戲當中,畫面里會隨機地彈射出一系列的水果與炸彈,玩家盡可能砍掉所有的水果而避免砍中炸彈,就可以完成游戲規定的任務。如果玩家可以一刀砍下畫面當中一連串的水果,則會有額外的獎勵,如圖1所示。

圖 1

現在假如你是“水果忍者”游戲的玩家,你要做的一件事情就是,將畫面當中的水果一刀砍下。這個問題看上去有些復雜,讓我們把問題簡化一些。我們將游戲世界想象成一個二維的平面。游戲當中的每個水果被簡化成一條一條的垂直於水平線的豎直線段。而一刀砍下我們也僅考慮成能否找到一條直線,使之可以穿過所有代表水果的線段。

圖 2

如圖2所示,其中綠色的垂直線段表示的就是一個一個的水果;灰色的虛線即表示穿過所有線段的某一條直線。可以從上圖當中看出,對於這樣一組線段的排列,我們是可以找到一刀切開所有水果的方案的。

另外,我們約定,如果某條直線恰好穿過了線段的端點也表示它砍中了這個線段所表示的水果。假如你是這樣一個功能的開發者,你要如何來找到一條穿過它們的直線呢?

輸入格式:

輸入在第一行給出一個正整數N(<=104),表示水果的個數。隨后N行,每行給出三個整數x,y1,y2,其間以空格分隔,表示一條端點為(x,y1)(x,y2)的水果,其中y1>y2。注意:給出的水果輸入集合一定存在一條可以將其全部穿過的直線,不需考慮不存在的情況。坐標為區間[10-6,106)內的整數。

輸出格式:

在一行中輸出穿過所有線段的直線上具有整數坐標的任意兩點p1(x1,y1),p2(x2,y2),格式為x1,y1,x2,y2。注意:本題答案不唯一,由特殊裁判程序判定,但一定存在四個坐標全是整數的解。

輸入樣例:

5
-30 -52 -84
38 22 -49
-99 -22 -99
48 59 -18
-36 -50 -72

輸出樣例:

-99 -99 -30 -52

首先如果線段X都相同(重合),那么就輸出最小的上端點和最大的下端點

上圖是通過對線段進行上下凸殼處理后的結果

上凸殼u維護一個棧,如果棧>=2並且p[i-1]在p[i-2]和p[i]的上方,就是(p[i]-p[i-1])X(p[i-2]-p[i-1])>0(叉積>0)

同理下凸殼d,叉積<0

根據題意,必然有解,那么上下凸殼不重合,答案就是圖中灰色的虛線

通過觀察能得到,答案可以在上下凸殼的折線上

枚舉上凸殼的折線,那么下凸殼的點必然在折線下,叉積<0

同理枚舉下凸殼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define LL long long
 5 #define fi first
 6 #define se second
 7 #define pa pair<int,int>
 8 int n;
 9 vector<int>p;
10 pa u[10000],d[10000];
11 int uc,dc;
12 map<int,int>vis,up,down;
13 int lx,ly,rx,ry;
14 bool pupl(pa p1,pa p2,pa p3)//p2在p1p3上
15 {
16     return (LL)(p3.fi-p1.fi)*(p2.se-p1.se)-(LL)(p2.fi-p1.fi)*(p3.se-p1.se)>0;
17 }
18 bool pdownl(pa p1,pa p2,pa p3)//p2在p1p3下
19 {
20     return (LL)(p3.fi-p1.fi)*(p2.se-p1.se)-(LL)(p2.fi-p1.fi)*(p3.se-p1.se)<0;
21 }
22 int main()
23 {
24     int x,y1,y2;
25     scanf("%d",&n);
26     for(int i=0;i<n;i++)
27     {
28         scanf("%d%d%d",&x,&y1,&y2);
29         if(!vis[x])
30         {
31             p.push_back(x);
32             vis[x]=1;
33             up[x]=y1;
34             down[x]=y2;
35         }
36         else
37         {
38             up[x]=min(up[x],y1);
39             down[x]=max(down[x],y2);
40         }
41     }
42     if(p.size()==1)lx=p[0],ly=up[p[0]],rx=p[0],ry=down[p[0]];
43     else
44     {
45         sort(p.begin(),p.end());
46         for(int i=0;i<p.size();i++)
47         {
48             while(uc>=2&&pupl(u[uc-2],u[uc-1],pa(p[i],up[p[i]])))uc--;
49             u[uc++]=pa(p[i],up[p[i]]);
50             while(dc>=2&&pdownl(d[dc-2],d[dc-1],pa(p[i],down[p[i]])))dc--;
51             d[dc++]=pa(p[i],down[p[i]]);
52         }
53         int i,j;
54         for(i=0;i<uc-1;i++)
55         {
56             for(j=0;j<dc;j++)//d[j]在u[i]和u[i+1]上NO
57                 if(pupl(u[i],d[j],u[i+1]))break;
58             if(j==dc)break;
59         }
60         if(i==uc-1)
61         {
62             for(i=0;i<dc-1;i++)
63             {
64                 for(j=0;j<uc;j++)//u[j]在d[i]和d[i+1]下NO
65                     if(pdownl(d[i],u[j],d[i+1]))break;
66                 if(j==uc)break;
67             }
68             lx=d[i].fi,ly=d[i].se,rx=d[i+1].fi,ry=d[i+1].se;
69         }
70         else
71         {
72             lx=u[i].fi,ly=u[i].se,rx=u[i+1].fi,ry=u[i+1].se;
73         }
74     }
75     printf("%d %d %d %d\n",lx,ly,rx,ry);
76     return 0;
77 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM