牛客.哈爾濱工程大學第十四屆程序設計競賽 (F.I.L)

F 小帆帆走迷宮

鏈接:https://ac.nowcoder.com/acm/contest/642/F
來源:牛客網

題目描述

小帆帆被困在一個 NxN 的方格矩陣迷宮,每個格子中都有一個整數 A[i][j]。小帆帆從迷宮起點(左上角)格子 A[1][1]開始走,每一步可以向右或向下移動,目標是移動到迷宮的出口右下角 A[N][N]。 小帆帆需要支付的費用包括路徑中經過的所有格子中的整數之和,以及改變移動方向需要支付的費用。 小帆帆第一次改變方向的費用是 1,第二次的費用是 2,第三次的費用是 4,…… 第 K 次的費用是2?−1。 請你幫小帆帆算出要離開迷宮的最小花費。
輸入描述:
第一行一個整數T,代表測試數據組數。每一組第一行一個整數N。 (1 ≤ N ≤ 100)以下N行每行N個整數,代表矩陣A。 (1 ≤ A[i][j] ≤ 100)
輸出描述:
從起點到終點路徑的最小花費。

示例1
輸入

2
1
10
3
1 3 5
1 1 2
5 1 1

輸出

10
9

枚舉每個格點對應可由哪些格點得來,然後枚舉上個結點的狀態,由於轉彎次數過多所以對於過多的情況直接不用枚舉

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 110;
int mp[maxn][maxn];//地圖
int f[maxn][maxn][30][2];
//記錄到達某個點的代價,轉彎的次數,當前的方向
//0表示向下走,1表示向右走
int w[25];

int main(){
	int T;
	cin >> T;
	w[0] = 1;
	for (int i = 1; i <= 25; i++)
		w[i] = w[i - 1] * 2;
	while (T--){
		int n;
		cin >> n;
		memset(f, 0x3f, sizeof f);
		for (int i = 1; i <= n;i++)
		for (int j = 1; j <= n; j++)
			cin >> mp[i][j];
		f[1][1][0][0] = mp[1][1];
		f[1][1][0][1] = mp[1][1];
		for (int i = 1; i <= n;i++)
		for (int j = 1; j <= n; j++){
			for (int k = 0; k <= 20; k++){
				f[i][j][k][0] = min(f[i][j][k][0], f[i][j-1][k][0] + mp[i][j]);//上個格子沒轉彎向下走
				f[i][j][k + 1][0] = min(f[i][j][k + 1][0], f[i][j - 1][k][1] + w[k] + mp[i][j]);
                //上面個格子轉彎後到達這個點
			}
			for (int k = 0; k <= 20; k++){
				f[i][j][k][1] = min(f[i][j][k][1], f[i - 1][j][k][1] + mp[i][j]);
				f[i][j][k + 1][1] = min(f[i][j][k + 1][1], f[i - 1][j][k][0] + w[k] + mp[i][j]);
                //同理向右的情況
			}
		}
		int  sum = 0x3f3f3f3f;
		for (int i = 0; i <= 20; i++)//枚舉轉彎次數爲幾時的總代價,取最小
			sum = min({ sum, f[n][n][i][0], f[n][n][i][1] });
		cout << sum << endl;
	}
	return 0;
}

I楊主席發糖

題目描述

19 年校賽的結果已經出爐,爲了對大家的積極參與表示感謝,楊主席準備拿出他的工資給大家發福利。 所有參賽選手排成一排,每位同學都對於有一個量化的得分(當然,得分越高越好)。楊主席已事先知道選手們的排隊順序以及個人的得分,他將一個一個給大家發糖。 楊主席是個有原則的男人,但他原則也是有限的。所謂有原則是指:分數高的一定比分數低的能拿到更多的糖果且分數 一樣的拿到的糖果一樣多;所謂原則是有限的又是指:剛剛說的原則僅對排隊中相鄰的兩人生效,且允許有人拿不到糖果(楊主席是個窮逼)。 楊主席並不想多花一分錢買額外的糖,於是他想知道在各種情況下最少需要購入幾塊糖。
輸入描述:
首先是一個整數T,表示數據輸入的組數,T<=20。對於每組數據,有兩行:(1)一個整數n,表示隊列中的人數,0 < n <= 1000。(2)n個整數a[0] … a[n-1],表示按隊列順序每個人的得分,注意可能會有同分的情況,保證a[i]是int類型的。
輸出描述:
對應T行,每行即對應每組輸入的最少購入糖數結果。

示例1

輸入

2
6
12 13 14 5 10 13
6
2 2 2 2 2 2

輸出

6
0

對於當前位置用數組分別前後掃一遍記錄相連的有幾個比自己小的,最後用數組遍歷取每個位置的最大值求和

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int f[maxn], g[maxn], a[maxn];
int main(){
	int T;
	cin >> T;
	while (T--){
		int n;
		cin >> n;
		memset(f, 0, sizeof f);
		memset(g, 0, sizeof g);
		for (int i = 1; i <= n; i++)
			cin >> a[i];
		for (int i = 2; i <= n; i++){
			if (a[i] == a[i - 1])
				f[i] = f[i - 1];
			else if (a[i] > a[i - 1])
				f[i] = f[i - 1] + 1;
			//else f[i] = 0;
		}
		for (int i = n - 1; i >= 1; i--){
			if (a[i] > a[i + 1])
				g[i] = g[i + 1] + 1;
			else if (a[i] == a[i + 1])
				g[i] = g[i + 1];
			//else g[i] = 0;
		}
		int sum = 0;
		for (int i = 1; i <= n; i++){
			sum += max(g[i], f[i]);
		}
		cout << sum << endl;
	}
	return 0;
}

L.實際問題

題目描述

本題的出題人在實習(摸魚)中遇到了一個非常有意思的問題,這個問題的核心即需要枚舉“組合”。 組合即數學上的“C”的概念,我們知道 C(x,y)=y!/x!/(y-x)! 如果我們想枚舉 C(3,4),我們有: 1 2 3 1 2 4 1 3 4 2 3 4 這道題就是這個意思,當然爲了簡化輸出,我們只要你給出按順序的第 k 個組合即可,如 C(3,4)的第 3 個是:1 3 4 注意組合內部是無序的,但是我們希望得到一個遞增順序的結果,即結果是 1 3 4,而非諸如 1 4 3 之流。
輸入描述:
首先是一個整數T,表示數據輸入的組數,T<=10。對於每組數據,一行三個數n,m,k:欲求C(m,n)的第k個組合。保證n<=100000,m<=n,k<=1000000,k<=C(m,n)。
輸出描述:
對應T行,每行即結果。

輸入

2
6 3 10
100 5 1000

輸出

1 5 6
1 2 3 14 99

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 1e5 + 5;
ll num[maxn];
int n, m, k, flag;
int cnt;
void dfs(int x, int y){//y爲這組的第幾個
	if (flag) return;
	if (y == m+1){
		cnt++;
		if (cnt == k){
			for (int i = 1; i < m; i++)
				cout << num[i] << " ";
			cout << num[m] << endl;
			flag = 1;
		}
		return;
	}
	for (int i = x; i <= n - m + y; i++){//選下一個或者不選
		num[y] = i;
		dfs(i + 1, y + 1);//選過不能重複選  i+1
		if (flag) return;
	}
}
int main(){
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n >> m >> k;
		memset(num, 0, sizeof num);
		flag = 0;
		cnt = 0;
		dfs(1, 1);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章