CF-gym-103405-Island Tour-思维

Island Tour
Iceland by Irena Jackson, CC0 Public Domain
Tijmen, Annemarie and Imme are visiting Iceland, a beautiful island country located in the middle of the Atlantic
Ocean. To see as much of the island as possible, they would
like to visit all of the tourist attractions on the Ring Road;
the main road that runs around the circular perimeter of the
island. There are n attractions, conveniently numbered from
1 to n in the order they appear along the road.
Unfortunately, current distancing measures only allow one
visitor at a time at any given attraction, so they have decided
to split up. Each person will start at a different attraction,
visiting the remaining attractions in circular order around
the Ring Road, i.e. a person starting their tour at attraction i visits the attractions in the order i,
i + 1, . . ., n, 1, . . ., i − 1.
They know how long it takes to travel from one attraction to the next and how much time
each person is going to spend at each attraction. They will each start their tour at the same
time and—due to their impatience—will follow their plan without any waiting. Help Tijmen,
Annemarie and Imme decide where each person should start their tour such that there never
comes a time where more than one person is located at the same attraction. A person may enter
an attraction at the same moment another person leaves the attraction, and when a person is
finished visiting their last attraction they will immediately leave the attraction and return to their
hotel.
Input
The input consists of:
• One line with an integer n (1 ≤ n ≤ 400), the number of tourist attractions.
• One line with n integers d1, . . . , dn (1 ≤ di ≤ 106
for each i), where di
is the travel time
in minutes from tourist attraction i to i + 1 (or to 1 when i = n).
• For each of Tijmen, Annemarie and Imme:
– One line with n integers t1, . . . , tn (1 ≤ ti ≤ 106
for each i), where ti
is the time in
minutes that the given person is going to spend at attraction i.
Output
If there is a valid assignment, output one line with three integers, the starting attraction for
each person. Otherwise, output “impossible”. If there are multiple valid solutions, you may
output any one of them.

cf题目

题意:
题目很长,意思简单来说就是
从n个数里面选择三个不同的数分配个三个人作为初始状态,然后每个人有n个状态(在某个时间段<开区间>占据某个数),如何分配使某个数在同一时间只能被一个人占据。

题解:
选择三个数复杂度o(n^3),但是对于每个人的状态需要o(n)才能退推出来(不要说预处理某个人在某个初始状态情况下对于每个数的占据状态,因为p[N][N]会爆栈)
这里就有一个非常无敌的思维,就是用低维遍历优化组合成为高维遍历,
用check[3][3][N][N]表示两两取各初始状态时是否满足题目条件,
然后再遍历n^3即可以o(1)判断是否可行。

//用低维遍历的组合来优化高维遍历、
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
const ll N = 507;
ll d[N], t[3][N];
vector<P>vis[N];
ll n;
bool comp[3][3][N][N];
int main() {
	cin >> n;
	for (ll i = 1; i <= n; i++) cin >> d[i];
	for (ll i = 0; i < 3; i++) 
		for (ll j = 1; j <= n; j++)cin >> t[i][j];
	for (ll t1 = 0; t1 < 3; t1++) 
		for (ll t2 = t1 + 1; t2 < 3; t2++) {
			for (ll i = 1; i <= n; i++) {
				for (ll j = 1; j <= n; j++) {
					for (ll i = 0; i <= n; i++)vis[i].clear();
					if (i == j)continue;
					ll now1 = i-1, now2 = j-1;
					ll nowt1 = 0, nowt2 = 0;
					for (ll k = 1; k <= n; k++) {
						now1++, now2++;
						if (now1 > n)now1 = 1;
						if (now2 > n)now2 = 1;
						vis[now1].push_back(P{ nowt1,nowt1 + t[t1][now1] });
						vis[now2].push_back(P{ nowt2,nowt2 + t[t2][now2] });
						nowt1 += t[t1][now1] + d[now1];
						nowt2 += t[t2][now2] + d[now2];
					}
					ll flag = 0;
					for (ll i = 1; i <= n; i++) {
						sort(vis[i].begin(), vis[i].end());
						if (vis[i][0].second > vis[i][1].first) { flag = 1; break; }
					}
					if (flag)comp[t1][t2][i][j] = false;
					else comp[t1][t2][i][j] = true;
				}
			}
		}
	ll flag = 0;
	for (ll i = 1; i <= n; i++) {
		for (ll j = 1; j <= n; j++) {
			for (ll k = 1; k <= n; k++) {
				if (i == j || j == k || i == k)continue;
				if (comp[0][1][i][j] && comp[0][2][i][k] && comp[1][2][j][k]) {
					printf("%lld %lld %lld", i, j, k);
					return 0;
				}
			}
		}
	}
	printf("impossible");
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值