暑假集训加试1

A. 蛋糕

区间\(DP\)板子
断环成链即可

code
#include<cstring>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<set>
#include<map>
#include<random>

using namespace std;

inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
typedef long long ll;
const int maxn = 2005;
ll f[maxn + maxn][maxn + maxn];
int a[maxn + maxn], n;
int main(){
	n = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i <= n; ++i)a[i + n] = a[i];
	for(int len = n; len >= 1; --len){
		for(int l = 1; l <= n + n - len + 1; ++l){
			int r = l + len - 1;
			if((n - len) & 1){
				if(a[l] > a[r])f[l + 1][r] = max(f[l + 1][r], f[l][r]);
				else f[l][r - 1] = max(f[l][r - 1], f[l][r]);
			}else{
				f[l + 1][r] = max(f[l + 1][r], f[l][r] + a[l]);
				f[l][r - 1] = max(f[l][r - 1], f[l][r] + a[r]);
			}
		}
	}
	ll ans = 0;
	for(int i = 1; i <= n + n; ++i)ans = max(ans, f[i][i - 1]);
	printf("%lld\n",ans);
	return 0;
}

B. 游戏

考场还想网络流来着,觉得不知道他是抛起来还是移动就放弃了类似思路,然而经典的拆点操作居然没有想起来.....

当然这题不用网络流,最短路即可

对每个点有三个状态\(0/1/2\)拆成\(3\)个点,\(0\)表示移动, \(1\)表示在横向抛,\(2\)表示在纵向抛

\(0 - > 1/ 2\)\(b\)的边

\(1/2 - > 0\)连最近的莉到该点的距离*C的边,表示由那个莉来接

相邻的\(0\)\(c\)

相邻的\(1/2\)\(a\)

code
#include<cstring>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<set>
#include<map>
#include<random>
using namespace std;
inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
typedef long long ll;
const int maxn = 1000005;
struct node{int x, y;}d[maxn];
ll a, b, c, ans, n;
int mp[505][505], dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0}, X, Y;
bool check(int x, int y){return x >= 0 && x <= X && y >= 0 && y <= Y;}
queue<node>q;
struct opt{
	int op, x, y; ll val;
	friend bool operator < (const opt & x, const opt & y){
		return x.val > y.val;
	}
};
priority_queue<opt>Q;
bool vis[3][505][505];
ll dis[3][505][505];
ll dij(){
	for(int i = 1; i <= n; ++i)q.push(d[i]), vis[0][d[i].x][d[i].y] = 1;
	while(!q.empty()){
		node now = q.front(); q.pop();
		for(int i = 0; i < 4; ++i){
			int nx = now.x + dx[i], ny = now.y + dy[i], nw = mp[now.x][now.y] + 1;
			if(check(nx, ny) && !vis[0][nx][ny]){
				vis[0][nx][ny] = 1; mp[nx][ny] = nw; q.push(node{nx, ny});
			}
		}
	}
	for(int i = 0; i <= X; ++i)
	  for(int j = 0; j <= Y; ++j)
	    vis[0][i][j] = 0;
	memset(dis, 0x3f, sizeof(dis));
	dis[0][d[1].x][d[1].y] = 0;
	Q.push(opt{0, d[1].x, d[1].y, 0});
	while(!Q.empty()){
		opt now = Q.top(); Q.pop();
		if(vis[now.op][now.x][now.y])continue;
		vis[now.op][now.x][now.y] = 1;
		if(now.op == 0){
			ll change = dis[now.op][now.x][now.y] + b;
			if(change < dis[1][now.x][now.y]){dis[1][now.x][now.y] = change; Q.push(opt{1, now.x, now.y, change});}
			if(change < dis[2][now.x][now.y]){dis[2][now.x][now.y] = change; Q.push(opt{2, now.x, now.y, change});}
			for(int i = 0; i < 4; ++i){
				int nx = now.x + dx[i], ny = now.y + dy[i];
				if(check(nx, ny) && dis[0][nx][ny] > dis[0][now.x][now.y] + c){
					dis[0][nx][ny] = dis[0][now.x][now.y] + c; 
					Q.push({0, nx, ny, dis[0][now.x][now.y] + c});
				}
			}
			continue;
		}
		ll ldis = dis[now.op][now.x][now.y] + mp[now.x][now.y] * c;
		if(dis[0][now.x][now.y] > ldis){dis[0][now.x][now.y] = ldis;Q.push(opt{0, now.x, now.y, ldis});}
		ll move = dis[now.op][now.x][now.y] + a;
		if(now.op == 1){
			if(check(now.x, now.y - 1) && dis[1][now.x][now.y - 1] > move){dis[1][now.x][now.y - 1] = move; Q.push(opt{1, now.x, now.y - 1, move});}
			if(check(now.x, now.y + 1) && dis[1][now.x][now.y + 1] > move){dis[1][now.x][now.y + 1] = move; Q.push(opt{1, now.x, now.y + 1, move});}
		}
		if(now.op == 2){
			if(check(now.x - 1, now.y) && dis[2][now.x - 1][now.y] > move){dis[2][now.x - 1][now.y] = move; Q.push(opt{2, now.x - 1, now.y, move});}
			if(check(now.x + 1, now.y) && dis[2][now.x + 1][now.y] > move){dis[2][now.x + 1][now.y] = move; Q.push(opt{2, now.x + 1, now.y, move});}
		}
	}
	return dis[0][d[n].x][d[n].y];
}
int main(){
	X = read(), Y = read();
	a = read(), b = read(), c = read();
	n = read();
	for(int i = 1; i <= n; ++i)d[i].x = read(), d[i].y = read();
	printf("%lld\n",dij());
	return 0;
}
posted @ 2022-08-19 18:01  Chen_jr  阅读(19)  评论(0编辑  收藏  举报