[CF1523F]Favorite Game

2024-03-16 22:58
文章标签 game favorite cf1523f

本文主要是介绍[CF1523F]Favorite Game,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Favorite Game

题解

**状压题

看到 n ⩽ 14 n\leqslant 14 n14应该很容易联系到状压。
我们先考虑如果要状压的话我们表示当前状态的话最多需要几维的状态。
当前已经激活了的传送塔的状态,当前位置,时间,完成任务数,总共四维。
但细细考率一下其实并不需要这么多维。
如果我们在某个完成任务的位置的话,我们应该业已完成这个任务,时间就是这个任务结束的时间,我们需要的是让次数的完成任务数最大,就用 g i , j g_{i,j} gi,j表示我们激活传送塔的状态为 i i i,刚完成了任务 j j j时完成任务的最大数量。
如果我们在某个传送塔的位置的话,当前位置在哪是不总要的,任意一个已激活的传送塔都可以被直接到达,对于完成任务数固定的情况,我们要让时间最小,就用 f i , j f_{i,j} fi,j表示我们激活传送塔的状态为 i i i,已完成 j j j个任务时的最短用时。

有了这两个状态,转移也比较明晰了。
对于某单个塔或任务到某个塔或任务的最短路就是 ∣ x i − x j ∣ + ∣ y i − y j ∣ |x_{i}-x_{j}|+|y_{i}-y_{j}| xixj+yiyj
对于激活塔状态为 i i i的情况,我们可以先预处理出它到某个任务或塔的最短路,时间复杂度 O ( 2 n ( n + m ) ) O\left(2^n(n+m)\right) O(2n(n+m))
g g g f f f之间的转移也是比较好想的,我们可以先枚举塔的状态 i i i,共有四种转移:

  • 从塔走到下一个塔,直接加上这之间的最短路。
  • 从塔去完成某个任务,当 f i , j + d i s i , k ⩽ t k f_{i,j}+dis_{i,k}\leqslant t_{k} fi,j+disi,ktk时, f i , j f_{i,j} fi,j就可以转移到 g i , k g_{i,k} gi,k
  • 从当前任务去完成下一个任务,当 t j + min ⁡ ( d i s i , k , d i s j , k ) ⩽ t k t_{j}+\min(dis_{i,k},dis_{j,k})\leqslant t_{k} tj+min(disi,k,disj,k)tk,时, g i , j g_{i,j} gi,j可以转移到 g i , k g_{i,k} gi,k
  • 用完成当前任务的状态 g g g去更新 f f f g i , j g_{i,j} gi,j可以更新到 f i , g i , j f_{i,g_{i,j}} fi,gi,j

总时间复杂度 O ( 2 n m ( n + m ) ) O\left(2^nm(n+m)\right) O(2nm(n+m))

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN (1<<14)+5
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int zero=500;
const LL jzm=2333;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int n,m,f[MAXN][105],g[MAXN][105],dis[MAXN][105],d[MAXN][20],ans;
struct ming{int x,y;}s[20];
struct task{int x,y,t;}a[105];
bool cmp(task x,task y){return x.t<y.t;}
signed main(){read(n);read(m);for(int i=1;i<=n;i++)read(s[i].x),read(s[i].y);for(int i=1;i<=m;i++)read(a[i].x),read(a[i].y),read(a[i].t);sort(a+1,a+m+1,cmp);for(int i=0;i<(1<<n);i++){for(int j=1;j<=n;j++)d[i][j]=INF;for(int j=1;j<=m;j++)dis[i][j]=INF;	}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)d[(1<<j-1)][i]=Fabs(s[j].x-s[i].x)+Fabs(s[j].y-s[i].y);for(int j=1;j<(1<<n);j++){int S1=j&(j-1);if(!S1||!(j^S1))continue;d[j][i]=min(d[S1][i],d[j^S1][i]);}}for(int i=1;i<=m;i++){for(int j=1;j<=n;j++)dis[(1<<j-1)][i]=Fabs(s[j].x-a[i].x)+Fabs(s[j].y-a[i].y);for(int j=1;j<(1<<n);j++){int S1=j&(j-1);if(!S1||!(j^S1))continue;dis[j][i]=min(dis[S1][i],dis[j^S1][i]);}}for(int i=0;i<(1<<n);i++)for(int j=0;j<=m;j++)f[i][j]=INF,g[i][j]=-INF;for(int i=1;i<=n;i++)f[(1<<i-1)][0]=0;for(int i=1;i<=m;i++)g[0][i]=1;for(int i=0;i<(1<<n);i++){for(int j=0;j<=m;j++){for(int k=1;k<=n;k++)if(!(i&(1<<k-1)))f[i|(1<<k-1)][j]=min(f[i][j]+d[i][k],f[i|(1<<k-1)][j]);for(int k=1;k<=m;k++)if(f[i][j]+dis[i][k]<=a[k].t)g[i][k]=max(g[i][k],j+1);}for(int j=1;j<=m;j++){for(int k=j+1;k<=m&&j;k++)if(a[k].t>=min(Fabs(a[j].x-a[k].x)+Fabs(a[j].y-a[k].y),dis[i][k])+a[j].t)g[i][k]=max(g[i][j]+1,g[i][k]);for(int k=1;k<=n;k++)if(g[i][j]>0&&!(i&(1<<k-1)))f[i|(1<<k-1)][g[i][j]]=min(a[j].t+min(d[i][k],Fabs(s[k].x-a[j].x)+Fabs(s[k].y-a[j].y)),f[i|(1<<k-1)][g[i][j]]);ans=max(ans,g[i][j]);}}printf("%d\n",ans);return 0;
}

谢谢!!!

这篇关于[CF1523F]Favorite Game的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

fzu 2275 Game KMP

Problem 2275 Game Time Limit: 1000 mSec    Memory Limit : 262144 KB  Problem Description Alice and Bob is playing a game. Each of them has a number. Alice’s number is A, and Bob’s number i

10400 -Game Show Math

这道题的话利用了暴力深搜,尽管给了20S,但是这样还会超时,所以就需要利用回溯进行减枝,因为是DFS,所以用一个数组vis[i][j]记录是否在状态i时候取到过j值,如果取到过的话,那么直接回溯(往后搜索已经没有意义了,之前到达这个状态的时候是无法得到结果的) 还有需要注意的地方就是题目的要求,每一步的结构都在(-32000,32000)之间,所以需要一步判断,如果在这个范围外直接回溯 最后一

【POJ】1733 Parity game 并查集

传送门:【POJ】1733 Parity game 题目大意:给你一个长度为n的01序列,再给你m句话,每句话是一个区间【L,R】,告诉你区间【L,R】中1的个数,现在你的任务是找到从第几句话开始说的和前面矛盾,出现第一次假话的时候前面有多少是真话。 题目分析:一开始看几乎没思路啊。后来没办法了,只能跑别人的博客去看看了。。。一看到说把一个区间【L,R】拆成两个区间【0,L-1】,

【HDU】5426 Rikka with Game【DP】

题目链接:【HDU】5426 Rikka with Game #include <bits/stdc++.h>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 100005 ;const int MAXE = 200005 ;

LeetCode 45 Jump Game II

题意: 给出一个步长数组nums,如果一个人站在i这个点上那么他可以向右最多走nums[i]步,求从左端点走到右端点的最少步数。 思路: 如果点x可以用dp[x]步到达,那么[ x + 1, x + nums[x] ]区间内的点都可以用dp[x] + 1步到达。 利用这个想法,可以O(n)的求出走一步可以到达哪些位置,走两步可以到达哪些位置,以此类推。 代码: clas

【论文笔记】Multi-Task Learning as a Bargaining Game

Abstract 本文将多任务学习中的梯度组合步骤视为一种讨价还价式博弈(bargaining game),通过游戏,各个任务协商出共识梯度更新方向。 在一定条件下,这种问题具有唯一解(Nash Bargaining Solution),可以作为多任务学习中的一种原则方法。 本文提出Nash-MTL,推导了其收敛性的理论保证。 1 Introduction 大部分MTL优化算法遵循一个通用方

android-Intent,Injector,Template,Adapter,Validation,Gesture,Game,Game Engine,Bluetooth...

Intent Intent PhotoPicker 图片选择 & 图片预览https://github.com/donglua/PhotoPicker Injector AndroidAnnotations Fast Android Development. Easy maintainance. https://github.com/excilys/androidannotations

HDU5515 Game of Flying Circus(二分)

题意:题解有翻译,然后自己拦截对手时候可以任意走,当然是直线最快啦 题解:http://www.cnblogs.com/qscqesze/p/4931912.html #include<bits/stdc++.h>using namespace std;#define LL long long#define pb push_back#define X first#define Y

hdu 1846 Brave Game 巴什博奕

Description 十年前读大学的时候,中国每年都要从国外引进一些电影大片,其中有一部电影就叫《勇敢者的游戏》(英文名称:Zathura),一直到现在,我依然对于电影中的部分电脑特技印象深刻。  今天,大家选择上机考试,就是一种勇敢(brave)的选择;这个短学期,我们讲的是博弈(game)专题;所以,大家现在玩的也是“勇敢者的游戏”,这也是我命名这个题目的原因。  当然,除了

hdu 1524 A Chess Game 博弈论

题意: 两个人在一个有向五环图上面走棋子,每次只能走一步,最后谁 * 没有棋子可走就败,然后棋子可以重叠,并且有n个棋子。要求判断 * 先手的胜负。 纠结了好长时间一直在想为什么sg函数要呢么定义然后看了各种博客但是只是讲了,定义的内容却很少有讲为什么的。。。。 Description Let's design a new chess game. There are N