zoukankan      html  css  js  c++  java
  • BNU 25593 Prime Time 记忆化dp

    题目链接:点击打开链接

    题意:

    一个游戏由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
    ", ans.a,ans.b, ans.c);
    	}
    	return 0;
    }



  • 相关阅读:
    Jquery、Ajax实现新闻列表页分页功能
    html中文字溢出处理(text-overflow)
    canvas图像绘制过程中的注意
    问题账户需求分析
    2016年秋季个人阅读计划
    阅读笔记之我们应当怎样做需求分析
    软件工程课个人总结
    人月神话阅读笔记—第四章
    人月神话阅读笔记—第三章
    人月神话阅读笔记—序言及第一、二章
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6917865.html
Copyright © 2011-2022 走看看