USACO 2015 December Contest, Gold 题解

tmd花了三个小时切了这套卷子,不甘心。

18:00 BEGIN

18:37 T1 WA 58

18:51 T1 AC

17:26 T2 AC

20:49 T3 WA 34

20:56 T3 AC

T1 High Card Low Card (Gold)

很快能想到贪心。

类似于田忌赛马那样,如果我方当前最好的card无法赢敌方的,那么就用最差的card去怼掉对方最好的;否则赢就是了

首先能赢就赢很明显;因为如果你这句不应放到后面去明显不会更优

用差的抵掉也很显而易见; 最差的作用最低,那么既然没人能赢他,那你就当替罪羊吧。

于是随便枚举一下时间复杂度O(n)

#include <bits/stdc++.h>
using namespace std ;
#define rep(i, a, b) for (int (i) = (a); (i) <= (b); (i)++)
#define per(i, a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define clr(a) memset(a, 0, sizeof(a))
#define ass(a, sum) memset(a, sum, sizeof(a))
#define lowbit(x) (x & -x)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define enter cout << endl
#define SZ(x) ((int)x.size())
typedef long long ll ;
typedef unsigned long long ull ;
typedef vector <int> vi ;
typedef pair <int, int> pii ;
typedef map <int, int> mii ;
typedef map <string, int> msi ;
const int N = 50010 ;
const int iinf = INT_MAX ;
const ll linf = 2e18 ;
const int MOD = 1000000007 ;
void print(int x) { cout << x << endl ; exit(0) ; }
void PRINT(string x) { cout << x << endl ; exit(0) ; }
void douout(double x){ printf("%lf\n", x + 0.0000000001) ; }

int n, ans, cnt ;
int a[N], b[N], app[N * 2] ;

bool cmp1(int a, int b) {return a > b ;}
bool cmp2(int a, int b) {return a < b ;}

signed main(){
	freopen("cardgame.in", "r", stdin) ;
	freopen("cardgame.out", "w", stdout) ;
	scanf("%d", &n) ;
	rep(i, 1, n) scanf("%d", &a[i]) ;
	sort(a + 1, a + n / 2 + 1, cmp1) ; sort(a + n / 2 + 1, a + n + 1, cmp2) ;
	rep(i, 1, n) app[a[i]] = 1 ;
	per(i, n * 2, 1) if (!app[i]) b[++cnt] = i ;
	sort(b + 1, b + n / 2 + 1, cmp1) ; sort(b + n / 2 + 1, b + n + 1, cmp2) ;
	int l = 1, r = n / 2, ll = 1, rr = n / 2 ; // 用B去匹配A, 对于每半片区间,越靠前越强
 	while (l <= r && ll <= rr) {
 		if (a[l] < b[ll]) { // 良马赢良马
 			l++, ll++, ans++ ;
		}
		else { // 用最劣马怼掉良马
			l++, rr-- ;
		}
	}
	l = n / 2 + 1, r = n, ll = n / 2 + 1, rr = n ;
	while (l <= r && ll <= rr) {
		if (a[l] > b[ll]) {
			l++, ll++, ans++ ;
		}
		else {
			l++, rr-- ;
		}
	}
	printf("%d\n", ans) ;
}
/*
10
10 5 8 1 2 3 11 4 16 19
*/

T2 Fruit Feast

最水的一道题目了

直接bfs+判重就行了

去掉文操10行啊 gold T2 真水啊

#include <bits/stdc++.h>
using namespace std ;
#define rep(i, a, b) for (int (i) = (a); (i) <= (b); (i)++)
#define per(i, a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define clr(a) memset(a, 0, sizeof(a))
#define ass(a, sum) memset(a, sum, sizeof(a))
#define lowbit(x) (x & -x)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define enter cout << endl
#define SZ(x) ((int)x.size())
typedef long long ll ;
typedef unsigned long long ull ;
typedef vector <int> vi ;
typedef pair <int, int> pii ;
typedef map <int, int> mii ;
typedef map <string, int> msi ;
const int N = 5000010 ;
const int iinf = INT_MAX ;
const ll linf = 2e18 ;
const int MOD = 1000000007 ;
void print(int x) { cout << x << endl ; exit(0) ; }
void PRINT(string x) { cout << x << endl ; exit(0) ; }
void douout(double x){ printf("%lf\n", x + 0.0000000001) ; }

int n, a, b, ans ;
queue <pii> q ;
int f[N][2] ;

signed main(){
	freopen("feast.in", "r", stdin) ;
	freopen("feast.out", "w", stdout) ;
	scanf("%d%d%d", &n, &a, &b) ;
	q.push(mp(0, 0)) ;
	while (!q.empty()) {
		pii now = q.front() ; q.pop() ;
		ans = max(ans, now.fi) ;
		if (now.fi + a <= n && !f[now.fi + a][now.se]) q.push(mp(now.fi + a, now.se)), f[now.fi + a][now.se] = 1 ;
		if (now.fi + b <= n && !f[now.fi + b][now.se]) q.push(mp(now.fi + b, now.se)), f[now.fi + b][now.se] = 1 ;
		if (now.fi != 0 && now.se == 0 && !f[now.fi / 2][now.se]) q.push(mp(now.fi / 2, 1)), f[now.fi / 2][now.se] = 1 ;
	}
	printf("%d\n", ans) ;
}

T3

题面表述的蛮奇怪的,emm用是个bfs的题目啊。

emm

弄一个struct

x, y, dir, sm

表示位置,方向,是否有气味

然后漂移的话就特殊处理一下。

然后发现自己光荣的MLE了,才34分

怎么写hash是个学问

emmm随便搞了个函数然后放进dis数组里

搞一搞AC了!!!

NBA!(NB啊!!!)

中间细节还是挺多的要注意什么sm搞来搞去,dir变来变去,没复制啦什么的

代码玄学的

#include <bits/stdc++.h>
using namespace std ;
#define rep(i, a, b) for (int (i) = (a); (i) <= (b); (i)++)
#define per(i, a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define clr(a) memset(a, 0, sizeof(a))
#define ass(a, sum) memset(a, sum, sizeof(a))
#define lowbit(x) (x & -x)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define enter cout << endl
#define SZ(x) ((int)x.size())
typedef long long ll ;
typedef unsigned long long ull ;
typedef vector <int> vi ;
typedef pair <int, int> pii ;
typedef map <int, int> mii ;
typedef map <string, int> msi ;
const int N = 1010 ;
const int iinf = INT_MAX ;
const ll linf = 2e18 ;
const int MOD = 1000000007 ;
void print(int x) { cout << x << endl ; exit(0) ; }
void PRINT(string x) { cout << x << endl ; exit(0) ; }
void douout(double x){ printf("%lf\n", x + 0.0000000001) ; }
const int dx[4] = {-1, 0, 1, 0} ;
const int dy[4] = {0, 1, 0, -1} ;

int n, m ;
int a[N][N] ;
int dis[10000000] ;

struct sta {
	int x, y, dir, sm ;
	int idx ;
	void h() {
		idx = ((x * 1000 + y + (dir + 1) * 1000000) << 1) | sm ;
	}
} ;

bool ok(int x, int y) {
	if (x < 1 || y < 1 || x > n || y > m) return 0 ;
	return 1 ;
}

int bfs() {
// | 0:无法通过 | 1:随便通过 | 2:通过并带上气味 | 3:有气体通过 | 4:紫色,漂移 |
	sta s = (sta) {1, 1, -1, 0} ; s.h() ;
	queue <sta> q ; q.push(s) ; dis[s.idx] = 0 ;
	while (!q.empty()) {
		sta lst = q.front() ; q.pop() ;
		if (lst.x == n && lst.y == m) return dis[lst.idx] ;
		if (lst.dir != -1) {
			sta now = lst ; now.sm = 0 ;
			now.x += dx[now.dir], now.y += dy[now.dir] ;
			int col = a[now.x][now.y] ;
			if (ok(now.x, now.y) && col != 0 && col != 3) {
				if (col != 4) now.dir = -1 ;
				if (col == 2) now.sm = 1 ;
				now.h() ;
				if (dis[now.idx] == -1) {
					dis[now.idx] = dis[lst.idx] + 1 ;
					q.push(now) ;
				}
				continue ;
			}
			lst.dir = -1 ;
		}
		for (int i = 0; i < 4; i++) {
			sta now = lst ;
			now.x += dx[i], now.y += dy[i] ;
			int col = a[now.x][now.y] ;
			if (!ok(now.x, now.y) || col == 0) continue ;
			if (col == 3 && !now.sm) continue ;
			if (col == 2) now.sm = 1 ;
			if (col == 4) now.dir = i, now.sm = 0 ;
			now.h() ;
			if (dis[now.idx] == -1) {
				dis[now.idx] = dis[lst.idx] + 1 ;
				q.push(now) ;
			}
		}
	}
	return -1 ;
}

signed main(){
	freopen("dream.in", "r", stdin) ;
	freopen("dream.out", "w", stdout) ;
	scanf("%d%d", &n, &m) ;
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++)
	scanf("%d", &a[i][j]) ;
	ass(dis, -1) ;
	cout << bfs() << endl ;
}

完美撒花。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值