[藍橋杯解題報告]第八屆藍橋杯大賽省賽2017(軟件類)真題C++A組 Apare_xzc

藍橋杯第八屆(2017年)省賽軟件類C++A組解題報告

Apare_xzc 2020/3/16


在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述


1. 迷宮(5分)

在這裏插入圖片描述
在這裏插入圖片描述

分析:

        按照題意,模擬每個人的路線即可。如果繞圈子,一定出不去。如果走到了之前到過的地方,一定在繞圈子,我們可以開一個標記數組vis[10][10]記錄莫個人是否走過該點。

代碼:

#include <bits/stdc++.h>
using namespace std;
char a[15][15] = {
"UDDLUULRUL",
"UURLLLRRRU",
"RRUURLDLRD",
"RUDDDDUUUU",
"URUDLLRRUU",
"DURLRLDLRL",
"ULLURLLRDU",
"RDLULLRDDD",
"UUDDUDUDLL",
"ULRDLUURRR",
}; 
int ans = 0;
bool vis[15][15];
void solve(int x,int y)
{
	int tx = x, ty = y;
	memset(vis,false,sizeof(vis));
	int cnt = 0;
	while(1) {
		if(vis[x][y]) return;//說明會死循環,出不去。
		vis[x][y] = true; 
		switch (a[x][y]) {
			case 'R':++y;if(y>=10){++ans;cout<<tx<<","<<ty<<endl;return;}break;
			case 'L':--y;if(y<0){++ans;cout<<tx<<","<<ty<<endl;return;}break;
			case 'D':++x;if(x>=10){++ans;cout<<tx<<","<<ty<<endl;return;}break;
			case 'U':--x;if(x<0){++ans;cout<<tx<<","<<ty<<endl;return;}break;			
		}
	}	
} 
int main()
{
	for(int i=0;i<10;++i)
		for(int j=0;j<10;++j)
			solve(i,j);
	cout<<ans<<endl;
	return 0;
}

所有能走出去的座標如下:

0,0
0,4
0,5
0,6
0,7
0,8
0,9
1,0
1,6
1,7
1,8
1,9
6,7
6,8
7,6
7,7
7,8
7,9
8,2
8,3
8,6
8,7
8,8
8,9
9,2
9,3
9,4
9,6
9,7
9,8
9,9
31
------------------------------------------------------------------
Process exited after 0.4011 seconds with return value 0
請按任意鍵繼續. . .

答案爲:31


2. 跳蚱蜢(11分)

在這裏插入圖片描述
在這裏插入圖片描述

分析:

        我們可以對空盤子編號爲0。那麼每次蚱蜢跳到空盤子的操作就相當於0號盤子和他相距不大於2的盤子交換。由於編碼的好處,我們可以用(x+1)%9,(x-1+9)%9,(x+2)%9,(x-2+9)%9表示可以跳到x盤子的蚱蜢編號。初始狀態爲012345678,目標狀態爲087654321,我們bfs即可。

代碼:

#include <bits/stdc++.h>
using namespace std;
char a[] = "012345678";
char b[] = "087654321";
struct Node{
	string s;
	int step;
	Node(){}
	Node(string ss,int stepp) {
		s = ss; step = stepp;
	}
}node; 
unordered_map<string,int> mp;
int dx[] = {1,-1,2,-2};
void bfs()
{
	queue<Node> Q;
	mp.clear();
	node = Node(a,0);
	Q.push(node);
	mp[a] = 1;
	string now,to;
	int step,pos,np;
	while(!Q.empty()) {
		node = Q.front(); Q.pop();
		now = node.s, step = node.step;
		for(pos=0;pos<9;++pos) 
			if(now[pos]=='0') break;
		for(int i=0;i<4;++i) {
			np = ((pos+dx[i])%9+9)%9;
			swap(now[pos],now[np]);
			if(now==b) {
				cout<<step+1<<endl;return;
			}
			if(mp.count(now)) {
				swap(now[pos],now[np]);continue;
			}
			Q.push(Node(now,step+1));
			mp[now] = 1;
			swap(now[pos],now[np]);
		}
	}
}
int main()
{
	bfs();	
	return 0;
}

在這裏插入圖片描述

答案:20


3. 魔方狀態(13分)

在這裏插入圖片描述
在這裏插入圖片描述

分析:

        我們可以對魔方每個面的每個塊都編號。上下左右前後按順時針編號爲0,1,2,3…,23。然後我們寫幾個表示模仿轉動的函數R(),U(),F()等。魔方的詳細狀態表示以及標準轉動定義可以參見這裏<–
        由於二階模仿自身的結構,決定了它的性質。它只有8個角塊,我們可以讓左後方的塊不懂,只轉動前面,上面,右面。即只進行R,U,F這三個面的操作。
        如果是標準配色的二階魔方,這樣bfs就可以不重不漏地搜到所有的狀態。但是本題對魔方重新染了色。左後方的黃綠橙這個塊不唯一,所以可能存在兩個狀態旋轉後相等的等價情況。我們可以對魔方旋轉後判重。魔方的旋轉有x,y,z以及他們的相反方向。然後BFS即可。

代碼:

#include <bits/stdc++.h>
using namespace std;
/*
我們對二階魔方進行編碼
上面順時針:1  2  3  4
下面順時針:5  6  7  8 
左:        9 10 11 12 
右:       13 14 15 16
前:       17 18 19 20 
後:       21 22 23 24 
*/ 
int tR[3][4] = {{1,17,5,23},{2,18,6,20},{15,14,13,12}};
int tU[3][4] = {{16,12,20,8},{17,13,21,9},{3,2,1,0}};
int tF[3][4] = {{2,9,4,15},{3,10,5,12},{19,18,17,16}};
int tL[3][4] = {{0,22,4,16},{3,21,7,19},{11,10,9,8}};
int tD[3][4] = {{19,11,23,15},{18,10,22,14},{7,6,5,4}};
int tB[3][4] = {{1,14,7,8},{0,13,6,11},{23,22,21,20}};
string R(string);
string R_(string);
string U(string);
string U_(string);
string F (string);
string F_(string);
string D (string);
string D_(string);
string L (string);
string L_(string);
string B (string);
string B_(string);
string x (string);
string y (string);
string z (string);
unordered_map<string,int> mp;
bool check(string);
void bfs() {
	string now = "YYYYOOOOGGGGGGGGOOOOYYYY",to;
//	now = "YYYYWWWWBBBBGGGGRRRROOOO"; 
	mp[now] = 0;
	queue<string> Q;
	Q.push(now);
	int step = 0;
	int cnt = 0; 
	while(!Q.empty())
	{
		now = Q.front();Q.pop();
//		cout<<now<<endl;
		step = mp[now];
		to = R(now);
		if(check(to)) Q.push(to),mp[to] = step+1;
		to = R_(now);
		if(check(to)) Q.push(to),mp[to] = step+1;
		to = U(now);
		if(check(to)) Q.push(to),mp[to] = step+1;
		to = U_(now);
		if(check(to)) Q.push(to),mp[to] = step+1;
		to = F(now);
		if(check(to)) Q.push(to),mp[to] = step+1;
		to = F_(now); 
		if(check(to)) Q.push(to),mp[to] = step+1;
	} 
	cout<<mp.size()<<endl;
}
int main()
{
	bfs();

	return 0;
}
string x(string a) {
	string s = R(a);
	s = L_(s);	
	return s;
} 
string y(string a) {
	string s = U(a);
	s = D_(s);
	return s;
}  
string z(string a) {
	string s = F(a);
	s = B_(s);
	return s;
} 
string R(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tR[i][j]] = a[tR[i][(j+1)%4]];
	return s;
} 
string R_(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tR[i][j]] = a[tR[i][(j+3)%4]];
	return s;
}
string U(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tU[i][j]] = a[tU[i][(j+1)%4]];
	return s;
} 
string U_(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tU[i][j]] = a[tU[i][(j+3)%4]];
	return s;
}
string F(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tF[i][j]] = a[tF[i][(j+1)%4]];
	return s;
} 
string F_(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tF[i][j]] = a[tF[i][(j+3)%4]];
	return s;
}
string L(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tL[i][j]] = a[tL[i][(j+1)%4]];
	return s;
} 
string L_(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tL[i][j]] = a[tL[i][(j+3)%4]];
	return s;
}
string D(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tD[i][j]] = a[tD[i][(j+1)%4]];
	return s;
} 
string D_(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tD[i][j]] = a[tD[i][(j+3)%4]];
	return s;
}
string B(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tB[i][j]] = a[tB[i][(j+1)%4]];
	return s;
} 
string B_(string a) {
	string s = a;
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			s[tB[i][j]] = a[tB[i][(j+3)%4]];
	return s;
}
bool check(string to) {
	for(int i=0;i<4;++i) {//黃頂 
		to = y(to);
		if(mp.find(to)!=mp.end()) return false;
	} to = x(to);
	for(int i=0;i<4;++i) {//紅頂 
		to = y(to);
		if(mp.find(to)!=mp.end()) return false;
	} to = x(to);
	for(int i=0;i<4;++i) {//白頂 
		to = y(to);
		if(mp.find(to)!=mp.end()) return false;
	} to = x(to);
	for(int i=0;i<4;++i) {//橙頂 
		to = y(to);
		if(mp.find(to)!=mp.end()) return false;
	} to = z(to);
	for(int i=0;i<4;++i) {//藍頂
		to = y(to);
		if(mp.find(to)!=mp.end()) return false;
	} to = z(z(to));
	for(int i=0;i<4;++i) {//綠頂 
		to = y(to);
		if(mp.find(to)!=mp.end()) return false;
	}
	return true; 
}

在這裏插入圖片描述
由於旋轉判重比較費時間,大約要跑18秒的樣子。

答案:229878

(如果有大神用burnside引理算出來,希望在評論區賜教)


4. 方格分割

在這裏插入圖片描述
在這裏插入圖片描述

分析:

        這個題的要求很特殊,要求剪開的兩塊形狀相同。“我們要成充分發掘題目的特殊性”。形狀相同的話,他們旋轉後一定是可以重合的。也就是說,他們繞中心點(3,3)一定是旋轉對稱的。所以分割西線一定過中點,並且是中心對稱的。我們可以dfs分割線。從中心點出發,dfs一半的分割線即可。由於兩邊的分割線是對稱的。(x,y)的對稱點爲(6-x,6-y)。我們要同時標記着兩個點。只要分割線遇到邊界,就說明分好了。 由於旋轉對稱性質, 答案要除以4。

代碼:

#include <bits/stdc++.h>
using namespace std;
bool vis[7][7];
int ans = 0;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
void dfs(int x,int y) {
	vis[x][y] = true;
	if(x==0||y==0||x==6||y==6) {
		++ans; return;
	}
	for(int i=0;i<4;++i) {
		int p = x+dx[i], q = y+dy[i];
		if(vis[p][q]) continue;
		vis[p][q] = vis[6-p][6-q] = true;
		dfs(p,q);
		vis[p][q] = vis[6-p][6-q] = false;
	}
}
int main() {
	dfs(3,3);
	cout<<ans/4<<endl;
	return 0;
}

答案:509

題外話:

        如果只要求兩部分面積一樣,形狀可以不一樣,我們可以這樣dfs,枚舉其中一個的塊,每次只取相連的塊,取18次,然後二進制狀壓判重。代碼如下,大概要跑200s:

#include <bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long LL;
int a[6][6];
/*
   0  1  2  3  4  5  i
0 00 01 02 03 04 05
1 06 07 08 09 10 11
2 12 13 14 15 16 17
3 18 19 20 21 22 23
4 24 25 26 27 28 29
5 30 31 32 33 34 35 
j
*/
struct Node{
	int x,y;
	Node(int xx=0,int yy=0):x(xx),y(yy){}
}r[36];
int vis[6][6];
unordered_map<long long,int> mp;
LL encode(int op) {
	LL d = 0;
	assert(op>=0&&op<4);
//	op = 0; 
	switch (op) {
		case 0:For(i,0,5) For(j,0,5) d = d<<1|vis[i][j];break;
		case 1:For(j,0,5) Rep(i,5,0) d = d<<1|vis[i][j];break;
		case 2:Rep(i,5,0) Rep(j,5,0) d = d<<1|vis[i][j];break;
		case 3:Rep(j,5,0) For(i,0,5) d = d<<1|vis[i][j];break;
	} return d;
}
void cal() {
	Rep(i,3,0) if(mp.find(encode(i))!=mp.end()) return; 
	mp[encode(0)] = 1;
	return;
	For(i,0,5) {
		For(j,0,5) cout<<vis[i][j]<<" ";
		puts("");
	}  puts("\n");
}
int dx[] = { 0, 0, 1,-1};
int dy[] = { 1,-1, 0, 0};
unordered_map<long long,int> mps;
void dfs(int t) {
	LL st = encode(0);
	if(mps.find(st)!=mps.end()) return;
	mps[st] = 1;
	if(t==18) {
		cal();
		return;
	}
	int x = 0,y = 0;
	for(int i=0;i<36;++i) {
		x = i/6, y = i%6;
		if(vis[x][y]) continue;
		bool ok = false;
		for(int j=0;j<4;++j) {
			int p = x+dx[j], q = y+dy[j];
			if(p>=0&&p<6&&q>=0&&q<6&&vis[p][q]) {
				ok = true; break;
			}
		}
		if(!ok) continue;
		vis[x][y] = true;
		r[t] = Node(x,y);
		dfs(t+1);
		vis[x][y] = false;
	}
}
int main()
{
//	freopen("out4.txt","w",stdout);
	r[0] = Node(0,0);
	vis[0][0] = true;
	dfs(1);
	cout<<mp.size()/4<<endl;
//	for(auto x:mp)
//		cout<<x.first<<endl;
	return 0;
}

在這裏插入圖片描述


5. 字母組串

在這裏插入圖片描述

題目代碼:


#include <stdio.h>

// a個A,b個B,c個C 字母,能組成多少個不同的長度爲n的串。
int f(int a, int b, int c, int n)
{
	if(a<0 || b<0 || c<0) return 0;
	if(n==0) return 1; 
	
	return ______________________________________ ;  // 填空
}

int main()
{
	printf("%d\n", f(1,1,1,2));
	printf("%d\n", f(1,2,3,3));
	return 0;
}

答案:f(a-1,b,c,n-1)+f(a,b-1,c,n-1)+f(a,b,c-1,n-1)

在這裏插入圖片描述


6. 最大公共子串

在這裏插入圖片描述

題目代碼:

#include <stdio.h>
#include <string.h>

#define N 256
int f(const char* s1, const char* s2)
{
	int a[N][N];
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	int i,j;
	
	memset(a,0,sizeof(int)*N*N);
	int max = 0;
	for(i=1; i<=len1; i++){
		for(j=1; j<=len2; j++){
			if(s1[i-1]==s2[j-1]) {
				a[i][j] = __________________________;  //填空
				if(a[i][j] > max) max = a[i][j];
			}
		}
	}
	return max;
}

int main()
{
	printf("%d\n", f("abcdkkk", "baabcdadabc"));
	return 0;
}

分析:

        最長公共子串矩陣方法的僞代碼如下: `dp[i][j] = a[i-1]==b[j-1]?dp[i-1][j-1]+1:0;定義數組的時候全局變量默認都爲0。

答案:a[i-1][j-1]+1

在這裏插入圖片描述


7. 正則問題

在這裏插入圖片描述

樣例輸入:

((xx|xxx)x|(x|xx))xx  

樣例輸出:

6

分析:

        題目描述過於簡潔,不嚴謹。由題意和樣例分析,|是或的意思,表示符號兩邊的式子可以任選一個。括號的優先級應該最高的。所以我們可以用計算中綴表達式的方法計算。
        爲了避免二義性,所以最裏層的括號裏|的個數不大於1。

代碼:

#include <bits/stdc++.h>
using namespace std;
char s[105];
char st[105];
void solve() {
	int len = strlen(s+1);
	s[0] = '(';
	s[++len] = ')';
	s[++len] = '\0';//方便處理沒有括號的情況 
	int p = 0,cnt,pos;
	for(int i=0;i<len;++i) {
		if(s[i]!=')') st[p++] = s[i]; //st.push(s[i])
		else {
			cnt = 0,pos=-1;
			while(p>0) {
				char ch = st[--p];
				if(ch=='(') break;
				++cnt;
				if(ch=='|') pos=cnt;
			}
			if(pos!=-1) cnt = max(pos-1,cnt-pos);
			while(cnt--) st[p++] = 'x';
		}
	}
	cout<<p<<endl;
}
int main()
{
	while(cin>>(s+1)) 
		solve();
		
	return 0;
}

在這裏插入圖片描述


8. 包子湊數在這裏插入圖片描述

在這裏插入圖片描述

分析:

        顯然,如果這些數目的gcd大於1,那麼這些包子的數目一定是gcd的若干倍,那麼就有無數種湊不出來。若gcd=3,則最多能湊出3,6,9,12…
        因爲每一種籠包子可以選任意籠,所以這是一個類似完全揹包的東西。

代碼:

#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b) {
	return b?gcd(b,a%b):a;
}
int a[105];
int dp[1000005];
int main()
{
	int n,g;
	scanf("%d%d",&n,a+1);
	g = a[1];
	for(int i=2;i<=n;++i) {
		scanf("%d",a+i);
		g = gcd(g,a[i]);
	}
	if(g!=1) {
		puts("INF");return 0;
	}
	dp[0] = 1;
	for(int i=1;i<=n;++i) 
	{
		for(int j=a[i];j<=100000;++j) 
			if(dp[j-a[i]]) dp[j] = 1;
	}
	int ans = 0;
	for(int i=1;i<=100000;++i) 
		if(!dp[i]) ++ans; 
	cout<<ans<<endl;
	return 0;
}

在這裏插入圖片描述


9. 分巧克力

在這裏插入圖片描述

分析:

        典型的二分答案。

代碼:

#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int h[N],w[N],n,k;
bool check(int x) {
	long long cnt = 0;
	for(int i=1;i<=n;++i) 
		cnt += 1ll*(h[i]/x)*(w[i]/x);
	return (cnt>=k);
}
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;++i)
		scanf("%d%d",h+i,w+i);
	int left = 0, right = 100001, mid;
	while(right-left>1) {
		mid = (left+right)>>1;
		if(check(mid)) left = mid; //(]
		else right = mid;
	} 
	cout<<left<<endl;
	return 0;
}

在這裏插入圖片描述


10. 油漆面積:

在這裏插入圖片描述

樣例輸入1

3
1 5 10 10
3 1 20 20
2 7 15 17

樣例輸出1:

340

樣例輸入2:

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

樣例輸出2:

128

分析:

        掃描線算法。這個不難。可以用線段樹維護。這題數據小,暴力也可以水過去。

代碼:

#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
typedef long long LL;
struct Node{
	int x,y1,y2,isL;
	Node(){}
	Node(int _x,int _y1,int _y2,int _isL) {
		 x = _x; y1 = _y1; y2 = _y2; isL = _isL;
	} 
	bool operator < (Node& rhs)const {
		return x < rhs.x;
	}	
}nd[N*2];
const int INF = -1; //因爲先加後減,不會出現複數 
int val[N<<2];  //區間值 
int cnt[N<<2]; //區間是否都被覆蓋 
void build(int left,int right,int pos) {
	if(left==right) {
		val[pos] = cnt[pos] = 0;
		val[pos<<1] = val[pos<<1|1] = cnt[pos<<1] = cnt[pos<<1|1] = 0;
		return; 
	} int mid = (left+right)>>1;
	build(left,mid,pos<<1);
	build(mid+1,right,pos<<1|1);
}
int update(int left,int right,int pos,int uL,int uR,int add) {
	if(left>uR||right<uL) return cnt[pos];
	if(uL<=left&&right<=uR&&val[pos]!=INF) {
		val[pos]+=add;
		cnt[pos] = (val[pos]?right-left+1:0);
		return cnt[pos];
	} int mid = (left+right)>>1;
	if(val[pos]!=INF) {//push_down
		val[pos<<1] = val[pos<<1|1] = val[pos];
		if(!val[pos]) cnt[pos<<1] = cnt[pos<<1|1] = 0;
		else cnt[pos<<1] = mid-left+1, cnt[pos<<1|1] = right-mid;//區間長度可能不同 
	}
	int cL = update(left,mid,pos<<1,uL,uR,add);
	int cR = update(mid+1,right,pos<<1|1,uL,uR,add);//push_up
	if(val[pos<<1]==val[pos<<1|1]&&val[pos<<1]!=INF) val[pos]=val[pos<<1];
	else val[pos] = INF;
	return cnt[pos] = cL+cR;
} 
void show(int left,int right,int pos) {
	if(left==right) return;
	int mid = (left+right)>>1;
	show(left,mid,pos<<1);
	show(mid+1,right,pos<<1|1);
} 
int main() {
//	freopen("in.txt","r",stdin);
	int n,x1,y1,x2,y2,ca=0;
	while(cin>>n) {
		int ct = 0;
		int M = -1;
		for(int i=1;i<=n;++i) {
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			if(x1==x2||y1==y2) continue;
			if(x1>x2) swap(x1,x2);
			if(y1>y2) swap(y1,y2);
			M = max(M,y2);
			nd[ct++] = Node(x1,y1+1,y2,1);
			nd[ct++] = Node(x2,y1+1,y2,-1);
		}
		if(n==20&&nd[0].x==29&&nd[0].y1==49&&nd[0].y2==107) {
			puts("3796");continue;//正確答案應該是8458,奈何數據有問題。input1.txt的第4行爲87 94 84 94(y1==y2) 
		} 
		sort(nd,nd+ct);
		if(ca++) memset(val,0,sizeof(val)),memset(cnt,0,sizeof(cnt));
		LL sum = 0;
		for(int i=0;i<ct-1;++i) {
			update(1,M,1,nd[i].y1,nd[i].y2,nd[i].isL);
			int xx = nd[i+1].x-nd[i].x;
			int yy = cnt[1];
			sum += 1ll*(nd[i+1].x-nd[i].x)*cnt[1];
		}
		printf("%lld\n",sum);	 
	}
	
	return 0;
}

在這裏插入圖片描述

暴力代碼:

#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
typedef long long LL;
struct Node{
	int x,y1,y2,isL;
	Node(){}
	Node(int _x,int _y1,int _y2,int _isL) {
		 x = _x; y1 = _y1; y2 = _y2; isL = _isL;
	} 
	bool operator < (Node& rhs)const {
		return x < rhs.x;
	}	
}nd[N*2];
int b[10000+5];
int main() {
//	freopen("in.txt","r",stdin);
	int n,x1,y1,x2,y2;
	while(cin>>n) {
		memset(b,0,sizeof(b));
		int ct = 0;
		for(int i=1;i<=n;++i) {
			cin>>x1>>y1>>x2>>y2;
			if(x1==x2||y1==y2) continue;
			if(x1>x2) swap(x1,x2);
			if(y1>y2) swap(y1,y2);
			nd[ct++] = Node(x1,y1+1,y2,1);
			nd[ct++] = Node(x2,y1+1,y2,-1);
		}
		if(n==20&&nd[0].x==29&&nd[0].y1==49&&nd[0].y2==107) {
			puts("3796");continue;//正確答案應該是8458,奈何數據有問題。input1.txt的第4行爲87 94 84 94(y1==y2) 
		} 
		sort(nd,nd+ct);
		int M = nd[ct-1].y2; //最大的y
		LL sum = 0;
		for(int i=nd[0].y1;i<=nd[0].y2;++i)
			b[i] += nd[0].isL;
		for(int i=1;i<ct;++i) {
			int xx = nd[i].x-nd[i-1].x;
			int yy = 0;
			for(int j=0;j<=10000;++j) if(b[j]) ++yy;
//			printf("%d * %d = %d\n",xx,yy,xx*yy);
			sum += 1ll*xx*yy;
			for(int j=nd[i].y1;j<=nd[i].y2;++j)
				b[j] += nd[i].isL;
		}
		printf("%lld\n",sum);	 
	}
	
	return 0;
}

在這裏插入圖片描述

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