gcd?人生赢家!
题目背景
原创:b2019dy
gcd是一个热爱游戏的人
题目描述
gcd最近在玩一个有趣的游戏
我们把这个游戏抽象成一张图,图上有n个点,我们需要寻找总计m件宝物,它们分布在图上,对于每件宝物而言,将会有一个前置集合S.只有当取得所有前置宝物时,才能获得该宝物。
gcd拥有一件神器,这件神器具有传送功能,它可以使用k次,可以传送到一个任意节点。
对于游戏而言,肯定会有额外的成就,这些成就会奖励一定的传送次数,成就的达成是满足集合S的一瞬间。
现在gcd想知道能最快通关的方法
输入输出格式
输入格式:
第一行:n,m,k
第二行:s表示成就的数量
以下s行,num表示需求多少个宝物,然后num个数,为所需宝物编号
第s+3行:a1,a2,⋯as表示成就的奖励次数
第s+4行:mp1,p2,⋯pm表示宝物的位置
第s+5行:e表示边的总数
以下e行:每行三个数x,y,z表示x与y之间有无向边连接,边权为z.
以下m行:每行一个数num表示第i个宝物的前置要求数,之后num个数,表示所需宝物编号
最后一行:st表示起点
输出格式:
最少时间
输入输出样例
输入样例#1: 复制
3 2 0
1
1 1
1
2 3
3
1 2 20
1 3 20
3 2 1
0
0
1
输出样例#1: 复制
20
输入样例#2: 复制
3 2 0
1
1 1
1
2 3
3
1 2 1
1 3 20
3 2 20
1 2
0
1
输出样例#2: 复制
40
说明
对于20%的数据,s=0
对于100%的数据:n≤200,m≤12,k≤4,s≤8,e≤20000
奖励次数总和不超过8
数据保证每两个宝物的位置不相同
可能有重边
数据保证有解
就是状压啦
想到三维状态\(f[i][j][k]\)表示那宝藏状态为\(i\)时,传送了\(j\)次,现在在位置\(k\)时的最少步数
预处理出每个合法状态和每个合法状态可以由那些状态转移过来
似乎还是很难用dp状态转移,用记忆化搜索会比较好写
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
#define M 1000001
#define max(a,b) ((a)>(b)? (a):(b))
#define min(a,b) ((a)<(b)? (a):(b))
using namespace std;
int i,m,n,j,k,f[4099][13][13],ss,t,s[20],g,gi[20],p[10001],e,d[201][202],x,y,z,l,q[M],st,w[100001],bl[100001],r[4500][4500],ans=0x3f3f3f3f;
int dp(int now,int bs,int t)
{
    if(now==(1<<m)-1) ans=min(ans,f[now][bs][t]);
    for(int i=1;i<=r[bl[now]][0];i++)
    {
        int y=0,x=0;
        if(bs>=k) for(int j=1;j<=ss;j++) if((s[j] ^now)==now-s[j])  y+=gi[j];
        int z=r[bl[now]][i]^now;
        while(z) z>>=1,x+=1;
        if(y+k>bs) if(f[r[bl[now]][i]][bs+1][x]>f[now][bs][t])
        {
            f[r[bl[now]][i]][bs+1][x]=f[now][bs][t];
            dp(r[bl[now]][i],bs+1,x);
        }
        if(f[r[bl[now]][i]][bs][x]>f[now][bs][t]+d[p[t]][p[x]])
        {
            f[r[bl[now]][i]][bs][x]=f[now][bs][t]+d[p[t]][p[x]];
            dp(r[bl[now]][i],bs,x);
        }
    }
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&ss);
    for(i=1;i<=ss;i++)
    {
        scanf("%d",&t);
        for(t;t;t--)
        {
            scanf("%d",&g);
            s[i]|=1<<(g-1);
        }
    }
    for(i=1;i<=ss;i++) scanf("%d",&gi[i]);
    for(i=1;i<=m;i++) scanf("%d",&p[i]);
    scanf("%d",&e);
    memset(d,0x3f,sizeof(d));
    for(i=1;i<=e;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        d[y][x]=d[x][y]=min(d[x][y],z);
    }
    for(l=1;l<=n;l++)
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(i!=j) d[j][i]=d[i][j]=min(d[i][l]+d[l][j],d[i][j]);
                else d[i][j]=0;
    for(i=1;i<=m;i++)
    {
        scanf("%d",&t);
        for(j=1;j<=t;j++)
        {
            scanf("%d",&g);
            q[i]|=1<<(g-1);
        }
    }
    scanf("%d",&st);
    for(i=1;i<1<<m;i++)
    {
        g=i; int b=1;
        while(g)
        {
            int h=g & -g, x=0;
            g-=h;
            while(h) x+=1, h>>=1;
            if(i-q[x]!=(i^q[x])) b=0;
            g-=h;
        }
        if(b) w[++w[0]]=i, bl[i]=w[0];
    }
    for(i=1;i<=w[0];i++)
    {
        t=w[i];
        while(t)
        {
            g=t & -t;
            if(bl[w[i]-g]) r[bl[w[i]-g]][++r[bl[w[i]-g]][0]]=w[i];
            t-=g;
        }
    }
    memset(f,0x3f,sizeof(f));
    t=1<<(st-1), y=0;
    for(j=1;j<=ss;j++) if(s[j]==t) y+=gi[j];
    for(i=0;i<m;i++)
    {
        t=1<<i, y=0;
        if(q[i+1]) continue;
        f[t][0][i+1]=d[st][p[i+1]];
        dp(t,0,i+1);
        if(k+y>=1)
        {
            f[t][1][i+1]=0;
            dp(t,1,i+1);
        }
    }
    printf("%d",ans);
}
gcd?人生赢家!的更多相关文章
- Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用
		OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ... 
- iOS 多线程之GCD的使用
		在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ... 
- 【swift】BlockOperation和GCD实用代码块
		//BlockOperation // // ViewController.swift import UIKit class ViewController: UIViewController { @I ... 
- 修改版: 小伙,多线程(GCD)看我就够了,骗你没好处!
		多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能.具有这种能力的系 ... 
- GCD的相关函数使用
		GCD 是iOS多线程实现方案之一,非常常用 英文翻译过来就是伟大的中枢调度器,也有人戏称为是牛逼的中枢调度器 是苹果公司为多核的并行运算提出的解决方案 1.一次性函数 dispatch_once 顾 ... 
- hdu1695 GCD(莫比乌斯反演)
		题意:求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d). 知识点: 莫比乌斯反演/*12*/ 线性筛求莫比乌 ... 
- hdu2588 GCD (欧拉函数)
		GCD 题意:输入N,M(2<=N<=1000000000, 1<=M<=N), 设1<=X<=N,求使gcd(X,N)>=M的X的个数. (文末有题) 知 ... 
- BZOJ 2820: YY的GCD [莫比乌斯反演]【学习笔记】
		2820: YY的GCD Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1624 Solved: 853[Submit][Status][Discu ... 
- BZOJ 2818: Gcd [欧拉函数 质数 线性筛]【学习笔记】
		2818: Gcd Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4436 Solved: 1957[Submit][Status][Discuss ... 
随机推荐
- Jquery Easy UI初步学习(三)数据增删改
			第二篇只是学了加载用datagrid加载数据,数据的增删改还没有做,今天主要是解决这个问题了. 在做增删改前需要弹出对应窗口,这就需要了解一下EasyUi的弹窗控件. 摘自:http://philoo ... 
- 撩课-Web大前端每天5道面试题-Day26
			1.vuejs与angularjs以及react的区别? .与AngularJS的区别 相同点: 都支持指令:内置指令和自定义指令. 都支持过滤器:内置过滤器和自定义过滤器. 都支持双向数据绑定. 都 ... 
- ActiveMQ 报错 Temporary Store limit is 51200 mb
			ERROR | Temporary Store limit is 51200 mb, whilst the temporary data directory: D:\tool\apache-actil ... 
- 浅谈TCP/IP(new 常见面试问题)
			1. TCP/IP重传机制,如何保证消息读到一个完整内容再反序列化 2. TCP四次回收比三次握手多了什么操作,什么时候会进入Time_await状态 3. 
- java,JsonFormat格式化日期问题
			今天使用以下代码格式日期字段 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; 发现这样渲 ... 
- MUI框架 选择器的使用
			js.css引用 <script type="text/javascript" src="librarys/mui/js/mui.min.js">& ... 
- Yii CGridView 关联表搜索排序实例
			在这篇文章中,我准备讲解如何在CGridView中搜索或者排序关联表中的某一行,通过给Yii Blog demo添加一个list页面. 首先,检查你的blog demo里的protected\mode ... 
- 【node】fs模块,文件和目录的操作
			检查文件是否存在,查询文件信息 fs.stat() fs.stat('./server.js', function (err, stat) { if (stat && stat.isF ... 
- linux客户端打印报表时操作系统的配置
			 报表打印是用applet方式操作的,所以客户端要有jre环境.如果客户端是windows系统的话,安装jre环境比较方便:如果客户端是linux系统的话,即使服务器端reportConfig.x ... 
- 2cmd 窗口 javac 错误:编码GBK的不可映射字符
			错误截图: 解决办法:第一步 第二步: 
