Cod sursa(job #945665)

Utilizator harababurelPuscas Sergiu harababurel Data 2 mai 2013 15:24:28
Problema Zombie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.36 kb
//O(N lg N)
//pe scurt: cand zombieul <i> intra pe strada, am 2 optiuni:
//	1 - folosesc dp[i-1] pentru zombii de dinainte, si 1 pentru zombieul curent, omorat singur. dp[i] = dp[i-1] + 1;
//	2 - folosesc vraja 2, si omor zombieul curent alaturi de toti zombii anteriori care se afla inca pe strada
//	    dp[i] = dp[j] + k
//	    unde j = cel mai recent zombie care nu se mai afla pe strada (o fost omorat deci anterior), asa ca ma folosesc de dp[j]
//	    si k = costul vrajii 2, cu care omor toti zombii aflati in prezent pe strada (j+1 -> i)
//la fiecare pas, aleg minimul dintre cele 2
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#define nmax 1000005
#define inf 1<<30
using namespace std;

int d, n, k, lo, hi, mid;
int dp[nmax], v[nmax];

int main() {
	ifstream f("zombie.in");
	ofstream g("zombie.out");
	
	f>>d>>n>>k;

	dp[0] = 0;
	for(int i=1; i<=n; i++) {
		f>>v[i];
		dp[i] = dp[i-1] + 1;		//pp. ca omor zombie-ul actual, singur

		//trebuie sa gasesc cel mai din stanga zombie care inca se afla pe strada
		//adica v[i] - v[j] <= d
		//<==> v[j] >= v[i]-d, v[j] = minim
		
		lo = 0;
		hi = i;
		while(hi - lo > 1) {
			mid = lo + (hi-lo) / 2;
			
			if(v[mid] < v[i]-d) lo = mid;
			else hi = mid;
		}
		//acum hi = cel mai din stanga zombie care se afla pe strada
		hi--;
		dp[i] = min(dp[i], dp[hi] + k);
	}
	
	g<<dp[n]<<"\n";

	return 0;
}