1. 程式人生 > >## 弱雞的第三次線上賽總結(TKK18no.6)(WIP)

## 弱雞的第三次線上賽總結(TKK18no.6)(WIP)

一些閒話

這次隔了這麼久才更這一次線上賽,其實中間有一丟丟原因,我先在這裡甩個鍋。其一是上次線上賽沒參加(不要和我提轉普通練習),去參加了志願者活動(心中有黨);其二是其實這次線上賽也有兩題沒過,琢磨了半天還是runtime或者memory limit。但想了想還是先把這次的WIP發出來,接受指導與建議。

第一題:字串替換

把字串s中的前m個字元c替換成字串d。
輸入一個正整數n,表示測試案例的數量。
每組案例由一個字串s,一個正整數m,一個字元c,一個字串d組成。(保證s裡至少會有m個c字元)
輸出
針對每組案例,輸出一個字串,表示根據描述變化後的字串。
每組案例輸出完都要換行。

沒什麼好說的,找出來,換一下,輸出來。

#include <iostream>
#include<string>
using namespace std;
int main()
{
	int m, n,i;
	string a, b; char c;
	cin >> n;
	while (n--)
	{
		cin >> a >> m >> c >> b;
		for (i = 0; i < a.length(); i++)
		{
			if (a[i] == c&&m!=0)
			{
				cout << b; m--;
			}
			else cout << a[i];
		}
		cout << endl;
	}
}

第二題:大柱的乘法

大柱規定了一種特別的乘法:當兩個數相乘時,列豎式計算;如果位數不同,則通過高位補0的方式對齊;運算時,每個數位分開計算,相同數位上下兩個數字相乘,取乘積的個位數作為該數位的值。例如:大柱乘法

這道題就按照題意實現即可,依位數補完再相乘即可。

#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
	int m, n, k;
	string a, b,t; char c;
	cin >> n;
	while (n--)
	{
		cin >> a >> b; t = "";
		int j = b.length() - 1;
		for (int i = a.length() - 1; i >= 0 ; i--)
		{
			t += char((((a[i] - '0')*(b[j] - '0')) % 10)+'0');
			j--;
			if(j<0)break;
		}
		int k = 0;
		for (int i = t.length() - 1; i >= 0; i--)
		{
			if (t[i] != '0'&&k==0)
			{
				k = 1; cout << t[i];
			}
			else if(k==1) cout << t[i];
		}
		if (k == 0)
			cout << 0;
		cout << endl;
	}
	return 0;
}

第三題:誰是臥底

曹操因為“雞肋”口令殺了楊修之後,覺得拿某個名詞當口令太容易讓文官們胡思亂想,所以使用了一個整數當口令,見面時喊這個整數來表明是自己人而不是敵方間諜。然而後來又遇到了個問題,士兵們記性不好,無法準確記住這個整數,於是曹操規定,只要喊的數字能和口令相差10之內(包括10)都算對,這下子所有士兵都能喊出正確範圍內的口令。有一天來了個蜀國的間諜混入了士兵中,曹操為了能分清總共m名士兵中,究竟誰是間諜,就讓他們各自在紙上寫下口令,同時交上來。假設魏國的士兵都各自寫出了正確範圍內的一個口令,而唯一一個蜀國的間諜是亂寫的。這時曹操的頭風病犯了,自己不記得口令是多少了,而且曹操生性多疑,不相信別人告訴他的口令。
問:曹操是否有可能根據士兵們交上來的口令,就能明確斷定出誰是間諜?
輸入
一個正整數n,表示n組案例。
每組案例先是一個正整數m(2<=m<=10000),表示連同間諜在內一共有m名士兵。然後是m個整數,分別表示第1、2、…、m名士兵寫的口令。案例保證最多隻會有一名間諜。
輸出
針對每組案例,如果無法區分誰是間諜,則輸出Cannot;如果能找出間諜,則輸出間諜是第幾個士兵(士兵編號從1到m)。
每組案例輸出完都要換行。

關於這道題,其實我是有些疑惑的,比如5,20,20,20,35是不是Cannot,但後來聽說好像不需要考慮這種可能。所以就是所有的數快排一下,然後要麼最大要麼最小,判斷哪個是臥底。

#include <iostream>
#include<algorithm>
#include<cmath>
using namespace std;
struct s
{
	int id, num;
};
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int m,k;
		cin >> m;
		if (m > 2)
		{
			s x[m];
			for (int i = 0; i < m; i++)
			{
				x[i].id = i + 1;
				cin >> x[i].num;
			}
			for (int i = 1; i < m; i++)
			{
				for (int j = 0; j < i; j++)
				{
					if (x[j].num>x[i].num)
						swap(x[i], x[j]);
				}
			}
			if (x[m - 1].num - x[0].num <= 20)
				cout << "Cannot";
			else
			{
				if (x[m - 1].num - 20 > x[1].num)
					cout << x[m-1].id;
				else cout << x [0].id;
			}
			cout << endl;
		}
		else
		{
			while (m--)
				cin >> k;
			cout << "Cannot" << endl;
		}
	}
	return 0;
}

第四題:貨郎擔

星星用扁擔挑了一攤貨去趕集。貨物一共有10件,每件貨物都有一定的重量。扁擔的兩邊各吊著一個筐,筐中可以裝任意多件貨物。星星希望兩個筐中的貨物重量差距儘可能小,以方便挑擔時保持平衡。問該重量差距最小是多少?

這道題應該是揹包的變形,同時因為案例比較小也可以用dfs做,但是不知道為什麼,我就是re轉mle。

丟臉,不發程式碼了。

第五題:字串出現次數

看看a字串裡出現了多少次b字串,規定如果多個b字串在a中的位置出現重疊,則都不計入次數。
例如abababa裡計算出現了多少次的aba時,由於所有的aba字串都存在與別的aba字串位置重疊,所以一共出現0次。

這個題也比較基礎,就是找出來b字串後把他的位置存好,和後一個比較是否小於b的長度。

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		string a,b;
		cin>>a>>b;
		int B=b.length();
		int r=-B-1;
		int sum=0;
		for(int i=0;i<a.length();i++)
		{
			if(a.substr(i,B)==b)
			{
				if(sum==1&&i-r<B)
			    {
			    	sum--;
				}
				if(i-r>=B)
				{
					sum=sum+1;
			    }
			    r=i; 
			}
		}
		cout<<sum<<endl;
	}
}

第六題:三英戰大柱

有m個勇敢的學弟想要線下賽組隊挑戰大柱,規則上至多隻允許3個學弟組隊。黃大佬作為學弟的精神領袖,想要暗地幫助學弟組隊,以達到最好的效果,即把所有題目都做出來。這m個學弟分別把所有題目的解題思路告訴了黃大佬,黃大佬記下了每個學弟按照解題思路是否可以做對每道題。然後黃大佬根據掌握的情況,想看看是否能夠選出3個學弟,使得每道題都至少有其中一個學弟能做對。
輸入
一個正整數n,表示有n組案例。每組案例先是兩個正整數m和p,分別表示學弟的數量和題目的數量(3<=m<=10, p<=500000)然後是m行資料,每行資料由p個字元組成,其中第i行第j個表示第i個學弟第j題做對還是做錯了。字元含義如下:A——正確,W——答案不對,T——超時,M——超記憶體,不會有除此之外的其它字元,每個字元之間有個空格,只有A表示做對。
輸出
針對每組案例,如果能夠選出3個學弟,使得每道題都至少有其中一個學弟能做對,那麼輸出Yes,否則輸出No。每組案例輸出完都要換行。

這題我也還沒a出來,也是可以實現但是mle,但這題還是貼一下程式碼,以供參考,因為案例比較小,所以我直接三重迴圈了。

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
	int m, p;
	cin>>m>>p;
	int x[m][p];
	for(int i=0;i<m;i++)
	{
		for(int j=0;j<p;j++)
		{
			char a;
			cin>>a;
			if(a=='A')x[i][j]=1;
			else x[i][j]=0;
		}
	}
	int sum=0; 
	for(int i=0;i<m;i++)
	{
		for(int j=0;j<m&&j!=i;j++)
		{
			for(int k=0;k<m&&k!=i&&k!=j;k++)
			{
				int b=1;
				for(int c=0;c<p;c++)
				{
					if(x[i][c]+x[j][c]+x[k][c]==0)
					{
						b=0;
					}
				}
				if(b==1)sum=1;
			}
		}
	}
	if(sum)cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	}
 } 

這時候還是runtime,因為我用的dev所以直接定義x[m][p],雖然這樣肯定不規範。

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int m, p;
		m = 10; p = 500000;
		bool **x = new bool*[m];
		for (int i = 0; i < m; i++)
		{
			x[i] = new bool[p];
		}
		for (int i = 0; i<m; i++)
		{
			for (int j = 0; j<p; j++)
			{
				char a;
				a = 'A';
				if (a == 'A')x[i][j] = 1;
				else x[i][j] = 0;
			}
		}
		bool sum = 0;
		for (int i = 0; i<m; i++)
		{
			for (int j = 0; j<m&&j != i; j++)
			{
				for (int k = 0; k<m&&k != i&&k != j; k++)
				{
					bool b = 1;
					for (int c = 0; c<p; c++)
					{
						if (x[i][c] + x[j][c] + x[k][c] == 0)
						{
							b = 0;
						}
					}
					if (b == 1)sum = 1;
				}
			}
		}
		if (sum)cout << "Yes" << endl;
		else cout << "No" << endl;
		for (int i = 0; i < m; i++)
		{
			delete[] x[i];
		}
		delete x;
	}
	return 0;
}

但是當我這樣new了一個二維陣列然後delete掉的時候,又變成了mle,就很難受。

還有一點閒話

就是因為這次線上賽是這學期最後一次,所以可能下學期再更,也有可能寒假隨緣更。希望發現我的bug的大佬(如果有空的話)可以評論或者+q309894263討論!(第四題用vector炸了)