“今日头条杯”首届湖北省大学程序设计竞赛 网络赛-E.Jump A Jump(取模最短路)

49 篇文章 0 订阅
12 篇文章 0 订阅

Problem Description

There's a very popular game called jump a jump recently.In order to get good marks, many people spend a lot of time

in this game.Wei is the master of jump a jump,he can easily get a very high score every time.

Recently he discovered that because of his muscle memory,he could not fully control his game score.

Now he wants you to help him figure out the nearest score that he can get from his desired score.

Every time he jumps, he chooses one from m distances,he can jump until he wants to end,and he can also use every distance

any times.

 

Input

Input contains multiple test cases.

For each test case,the first line has a number n(n <= 1e15) to indicate the score he desired.

The next line has a number m(m <= 2000), which indicates how many choices each step has.

The last line has m integers bi(1<=bi <= 5000) representing the ith distances.

Output

  For each test case,output is the absolute value of the difference between the nearest score he can get and his desired score.


 题意大概就是给一个n维向量X(xi>=0),让你求一个向量Y(yi>=0),使得X和Y的点积最接近一个给定的数n,本质还是取模最短路,可以取b1为模数跑最短路,设d[x]为模b1为x的步数中的最小值,那么显然d[x]+k*b1都可以被表示出来,所以求出d[x]后扫一遍就可以得到最接近n的值了.

 因为时间仓促所以数据造的水了一点,导致几个错误做法水了过去.

#include <bits/stdc++.h>
#define N 50005
#define MOD 1000000007
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
ll n,m,x,ans,d[N],b[N];
bool done[N];
priority_queue< pii,vector<pii>,greater<pii> > q;
int main()
{
    cin.sync_with_stdio(false);
    while(cin>>n>>m)
    {
		ans = 1e16;
		for(int i = 1;i <= m;i++) cin>>b[i];
		sort(b+1,b+1+m);
		memset(d,0x3f,sizeof(d));
		memset(done,0,sizeof(done));
		d[0] = 0;
		q.push(make_pair(d[0],0));
		while(!q.empty())
		{
			int u = q.top().second;
			q.pop();
			if(done[u]) continue;
			done[u] = true;
			for(int i = 1;i <= m;i++)
			 if(d[(b[i]+u) % b[1]] > d[u] + b[i])
			 {
		 		 d[(b[i]+u) % b[1]] = d[u] + b[i];
	 			 q.push(make_pair(d[(b[i]+u) % b[1]],(b[i]+u) % b[1]));
	 		 }
		}
		ll target = n % b[1];
		for(int i = 0;i < b[1];i++)
		{
			if(d[i] > n) 
			{
				ans = (d[i]-n) < ans ? d[i]-n : ans;
				continue;
			}
			ll Max = max(target,i*1ll),Min = min(target,i*1ll);
			ans = min(ans,min(Max-Min,b[1]-Max+Min));
		}
		cout<<ans<<endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值