【GDOI2017模拟二试4.12】石子游戏

2023-10-28 11:18

本文主要是介绍【GDOI2017模拟二试4.12】石子游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目大意

给出n个数a[i],将x改为y的代价为|x-y|,求将a变成xor和为零的最小代价。
1n15,0a[i]109

题解

考虑动态规划,按二进制从高到低,用 3n 的状态表示每个数是在k位之前是增加/不变/减少,设f[k][i][S][0/1]表示当前做到第k位,当前考虑第i位,S为每个数的状态,然后转移有:
1、若k位之前是不变,那么当前可以转成 增加/不变/减少
2、若k位之前是增加/减少,那么状态不变
时间复杂度是 O(32×n×3n)
然后是过不了的
考虑怎么把 3n 变成 2n ,就是说要把增加和减少归为同一类,对于一个数的减少,我们可以先把后面的位减成全部都为1,比如 (10100)2 可以减成 (10011)2 ,然后对于增加,就把后面的位全都变成0,这样做的好处是,当我们在后面的位里如果把增加的数的0变为1或把减少的数的1变为0都会产生贡献
对于已经确定了增加/减少的数我们称之为“不自由的”
那么可以设f[k][i][s][x][y]表示从高到低,做到第k位,当前考虑第i个数,是否自由的状态为s,当前位的xor和为x,已经确定的不自由的位在后面的位中的xor和为y
转移要分几种情况:
若第i位是自由的,那么可以考虑让它保持自由
或者将它变得不自由:
1、如果当前第k位为1,那么就要减少,算上贡献就是(a[i]&(mi[k+1]-1))-(mi[k]-1)
2、如果当前第k位为0,那么就要增加,算上贡献就是mi[k]-(a[i]&(mi[k+1]-1))
若第i位不自由,可以不更改状态直接转
或者将当前位改变,那么贡献为mi[k]

需要注意的地方是,状态中的y表示的是所有不自由位置的xor和,就是说当前位的状态不会影响这个y

Code

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long LL;
typedef double db;int get(){char ch;while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');if (ch=='-'){int s=0;while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';return -s;}int s=ch-'0';while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';return s;
}const int N = 16;
const int L = 33000;
const int W = 33;
const LL INF = 2e+10;
const int U = 31;LL f[2][N][L][2][2];//s:0 for free;1 for limited;
int T,n;
int a[N][W];
LL mi[W];
LL val[N];LL minll(LL x,LL y){if (x<y)return x;return y;
}int main(){freopen("stone.in","r",stdin);freopen("stone.out","w",stdout);T=get();mi[0]=1;fo(i,1,32)mi[i]=mi[i-1]<<1;while(T--){n=get();fo(i,1,n){int x=get();fd(u,31,0)if ((mi[u]&x)>0)a[i][u]=1;else a[i][u]=0;val[i]=x;}fo(u,0,1)fo(i,1,n)fo(s,0,mi[n]-1)fo(x,0,1)fo(y,0,1)f[u][i][s][x][y]=INF;int now=0;f[0][n][0][0][0]=0;fd(k,U,0){int t=now^1;fo(i,0,n)fo(s,0,mi[n]-1)fo(x,0,1)fo(y,0,1)f[t][i][s][x][y]=INF;fo(s,0,mi[n]-1)fo(x,0,1)f[t][0][s][x][x]=f[now][n][s][0][x];fo(i,1,n)fo(s,0,mi[n]-1){if ((mi[i-1]&s)==0){//free//still freefo(x,0,1)fo(y,0,1)f[t][i][s][x^a[i][k]][y]=minll(f[t][i][s][x^a[i][k]][y],f[t][i-1][s][x][y]);//set limitedif (a[i][k]){//-:set 1//f[t][i][s|mi[i-1]][x][y]  f[t][i-1][s][x][y]+(val[i]&(mi[k+1]-1))-(mi[k]-1)fo(x,0,1)fo(y,0,1)f[t][i][s|mi[i-1]][x][y^1]=minll(f[t][i][s|mi[i-1]][x][y^1],f[t][i-1][s][x][y]+(val[i]&(mi[k+1]-1))-(mi[k]-1));}else{//+;set 0fo(x,0,1)fo(y,0,1)f[t][i][s|mi[i-1]][x^1][y]=minll(f[t][i][s|mi[i-1]][x^1][y],f[t][i-1][s][x][y]+mi[k]-(val[i]&(mi[k+1]-1)));}}else{//stayfo(x,0,1)fo(y,0,1)f[t][i][s][x][y]=minll(f[t][i][s][x][y],f[t][i-1][s][x][y]);//transfo(x,0,1)fo(y,0,1)f[t][i][s][x^1][y]=minll(f[t][i][s][x^1][y],f[t][i-1][s][x][y]+mi[k]);}}now=t;}LL ans=INF;fo(s,0,mi[n]-1)fo(x,0,1)ans=minll(ans,f[now][n][s][0][x]);printf("%lld\n",ans);}fclose(stdin);fclose(stdout);return 0;
}

这篇关于【GDOI2017模拟二试4.12】石子游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/292836

相关文章

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

火柴游戏java版

代码 /*** 火柴游戏* <p>* <li>有24根火柴</li>* <li>组成 A + B = C 等式</li>* <li>总共有多少种适合方式?</li>* <br>* <h>分析:</h>* <li>除去"+"、"="四根,最多可用火柴根数20根。</li>* <li>全部用两根组合成"1",最大数值为1111。使用枚举法,A和B范围在0~1111,C为A+B。判断</li>** @

国产游戏行业的崛起与挑战:技术创新引领未来

国产游戏行业的崛起与挑战:技术创新引领未来 近年来,国产游戏行业蓬勃发展,技术水平不断提升,许多优秀作品在国际市场上崭露头角。从画面渲染到物理引擎,从AI技术到服务器架构,国产游戏已实现质的飞跃。然而,面对全球游戏市场的激烈竞争,国产游戏技术仍然面临诸多挑战。本文将探讨这些挑战,并展望未来的机遇,深入分析IT技术的创新将如何推动行业发展。 国产游戏技术现状 国产游戏在画面渲染、物理引擎、AI

【算法专场】模拟(下)

目录 前言 38. 外观数列 算法分析 算法思路 算法代码 1419. 数青蛙 算法分析 算法思路 算法代码  2671. 频率跟踪器 算法分析 算法思路 算法代码 前言 在前面我们已经讲解了什么是模拟算法,这篇主要是讲解在leetcode上遇到的一些模拟题目~ 38. 外观数列 算法分析 这道题其实就是要将连续且相同的字符替换成字符重复的次数+