1. 程式人生 > >BNU 25593 Prime Time 記憶化dp

BNU 25593 Prime Time 記憶化dp

cto ans 分開 人在 clas con pid target 意義

題目鏈接:點擊打開鏈接

題意:

一個遊戲由3個人輪流玩

每局遊戲由當中一名玩家選擇一個數字作為開始

目的:獲得最小的得分

對於當前玩家 O 。面對 u 這個數字

則他的操作有:

1、 計分 u +1 ,然後 u++;

2、計分 u / x, 然後 u /= x; 當中x為u的因子且x為素數

然後下一個玩家繼續上述操作

3個人各操作一次 為1輪

當一輪結束後,若u==1 則遊戲結束

每一個人的得分為 他全部計分記錄裏最小的數字


若在一輪結束前 u就==1, 那麽玩家的得分為本局遊戲的初始數

求:

每一個人在採取最優操作下玩n局遊戲的總得分(不同局得分相加)

輸入n表示n局遊戲

以下n行給定 人名縮寫+u

表示哪個玩家開始,他選擇了哪個數字

思路:

1、n局遊戲之間各不影響,所以分開考慮每局遊戲

2、對於一局遊戲。則我們能夠記憶化搜索出每一個數字u相應的狀態


顯然我們能夠得到若u為素數時 答案就是 { 1, u, u}

若u不為素數,則u能夠轉移到狀態v

在保證第一個數字最小的情況下,從越小的狀態轉移過來則結果越小


註意素數初始化時我們覺得是{prime, inf, inf} 這樣會得到一些不存在狀態,而不存在的狀態意義是本局遊戲的初值

#include <stdio.h>
#include <algorithm>
#include<iostream>
#include<string.h>
#include <math.h>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
#define N 100008
#define inf 100000000
#define ll int
ll prime[9599], primenum;
set<int>s;
void PRIME(ll Max_Prime){
	primenum = 0;
	prime[primenum++] = 2;
	for(ll i = 3; i <= Max_Prime; i+= 2)
		for(ll j = 0; j < primenum; j++)
			if(i%prime[j]==0)break;
			else if(prime[j] > sqrt((double)i) || j==primenum-1)
			{
				prime[primenum++] = i;
				break;
			}
}
struct node{
	int a,b,c,ok;
	node(int x=0,int y=0,int z=0,int yes=0):a(x),b(y),c(z),ok(yes){}
}dp[N];
void dfs(int u){
	if(dp[u].ok)return;
	int t, fir = inf, id = inf;
	for(int i = 0; prime[i] <= u; i++)if(u % prime[i]==0) {
		dfs(u/prime[i]);
		t = min(u/prime[i], dp[u/prime[i]].c);
		if(t < fir || (t == fir && u/prime[i] < id))
			fir = t, id = u/prime[i];
	}
	dfs(u+1);
	t = min(u+1, dp[u+1].c);
	if(t < fir || (t == fir && u+1 < id))
		fir = t, id = u+1;
	dp[u] = node( fir, dp[id].a, dp[id].b, true);
}
int main(){
	int i, n;
	PRIME(100007);
	s.clear();
	for(i = 0; i < N; i++) dp[i].ok = false;
	for(i = 0; i < primenum; i++) {
		dp[prime[i]] = node(1, inf, inf, true);
		s.insert(prime[i]);
	}
	dp[1] = node(1, 1, 1, true);
	while(~scanf("%d",&n)){
		node ans = node(0, 0, 0, true);
		while(n--){
			char ch[2]; int u;
			scanf("%s %d", ch, &u);
			dfs(u);
			node tmp = dp[u];
			if(tmp.a == inf) tmp.a = u;
			if(tmp.b == inf) tmp.b = u;
			if(tmp.c == inf) tmp.c = u;

			if(ch[0] == ‘O‘)
				ans.a += tmp.a, ans.b += tmp.b, ans.c += tmp.c;
			else if(ch[0] == ‘E‘)
				ans.b += tmp.a, ans.c += tmp.b, ans.a += tmp.c;
			else
				ans.c += tmp.a, ans.a += tmp.b, ans.b += tmp.c;
		}
		printf("%d %d %d\n", ans.a,ans.b, ans.c);
	}
	return 0;
}



BNU 25593 Prime Time 記憶化dp