题目:https://loj.ac/problem/2557

第一个点可以暴搜。

第三个点无依赖关系,k=3,可以 DP 。dp[ cr ][ i ][ j ] 表示前 cr 个任务、第一台机器最晚完成时间是 i 、第二台机器最晚完成时间是 j ,第三台机器最晚完成时间是多少。数组开 500 就行了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=,M=,K=,INF=1e9+;
int n,m,k,op,dp[N][M][M],pr[N][M][M][];
int t[N][K],r[K][K],prn[N];
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&op);
for(int i=;i<=n;i++)
for(int j=;j<=k;j++)
scanf("%d",&t[i][j]);
for(int i=;i<=k;i++)
for(int j=;j<=k;j++)
scanf("%d",&r[i][j]);
memset(dp,0x3f,sizeof dp);
dp[][][]=;
for(int cr=;cr<=n;cr++)
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
int w=t[cr][];
dp[cr][i][j]=dp[cr-][i][j]+w;
pr[cr][i][j][]=i; pr[cr][i][j][]=j;
w=t[cr][];
if(i>=w&&dp[cr-][i-w][j]<dp[cr][i][j])
{
dp[cr][i][j]=dp[cr-][i-w][j];
pr[cr][i][j][]=i-w; pr[cr][i][j][]=j;
}
w=t[cr][];
if(j>=w&&dp[cr-][i][j-w]<dp[cr][i][j])
{
dp[cr][i][j]=dp[cr-][i][j-w];
pr[cr][i][j][]=i; pr[cr][i][j][]=j-w;
}
}
int ans=INF,r0,r1;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
int d=Mx(Mx(i,j),dp[n][i][j]);
if(d<ans)ans=d,r0=i,r1=j;
}
for(int i=n;i;i--)
{
int t0=pr[i][r0][r1][],t1=pr[i][r0][r1][];
if(t0!=r0)prn[i]=; else if(t1!=r1)prn[i]=; else prn[i]=;
r0=t0; r1=t1;
}
for(int i=;i<=n;i++)printf("%d ",prn[i]);puts("");
return ;
}

第四个点连成三条编号有序的链 。 dp[ i ][ j ] 表示前 i 个任务、此刻在 j 点,最小时间总和。链断开的位置不用算“传输时间”即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=,K=,INF=1e9+;
int n,m,k,op,a[N],prn[N];
int t[N][K],r[K][K],dp[N][K],pr[N][K];
bool vis[N];
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&op);
for(int i=,u,v;i<=m;i++)
scanf("%d%d",&u,&v);
for(int i=;i<=n;i++)
for(int j=;j<=k;j++)
scanf("%d",&t[i][j]);
for(int i=;i<=k;i++)
for(int j=;j<=k;j++)
scanf("%d",&r[i][j]);
for(int j=;j<=k;j++)
dp[][j]=t[][j];
for(int i=;i<=n;i++)
{
if(i==||i==)
{
int rt=;
for(int l=;l<=k;l++)
if(dp[i-][l]<dp[i-][rt])rt=l;
for(int j=;j<=k;j++)
{
dp[i][j]=t[i][j]+dp[i-][rt];
pr[i][j]=rt;
}
continue;
}
for(int j=;j<=k;j++)
{
dp[i][j]=INF;
for(int l=;l<=k;l++)
if(dp[i-][l]+r[l][j]<dp[i][j])
{
dp[i][j]=dp[i-][l]+r[l][j];
pr[i][j]=l;
}
dp[i][j]+=t[i][j];
}
}
int ans=;
for(int j=;j<=k;j++)if(dp[n][j]<dp[n][ans])ans=j;
for(int i=n;i;i--)
prn[i]=ans,ans=pr[i][ans];
for(int i=;i<=n;i++)printf("%d ",prn[i]);puts("");
return ;
}

第七个点,发现每个任务在每个机器上的时间差不多,所以(看别人博客)发现方案应该是二分图匹配。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=,K=,M=N*K;
int n,m,k,op,lm=,hd[N],xnt,to[M],nxt[M],per[K],prn[N];
int t[N][K],r[K][K]; bool vis[K];
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
bool xyl(int cr)
{
for(int i=hd[cr],v;i;i=nxt[i])
if(!vis[v=to[i]])
{
vis[v]=;
if(!per[v]||xyl(per[v]))
{ per[v]=cr; return true;}
}
return false;
}
int main()
{
n=rdn();m=rdn();k=rdn();op=rdn();
for(int i=;i<=n;i++)
for(int j=;j<=k;j++) t[i][j]=rdn();
for(int i=;i<=k;i++)
for(int j=;j<=k;j++) r[i][j]=rdn();
for(int i=;i<=n;i++)
for(int j=;j<=k;j++)
if(t[i][j]<=lm)add(i,j);
for(int i=;i<=n;i++)
{
memset(vis,,sizeof vis);
xyl(i);
}
for(int i=;i<=k;i++)
if(per[i])prn[per[i]]=i;
for(int i=;i<=n;i++)printf("%d ",prn[i]);puts("");
return ;
}

剩下 op=1 的点,试图用模拟退火,但效果很不好,几乎没有什么改变。自己不是很了解随机化算法……

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<cmath>
#define db double
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=,M=,K=;
const db dec=0.988,eps=1e-;
int n,m,k,op,prn[N],a[N],b[N];
int t[N][K],r[K][K],ans;
struct Ed{
int x,y;
}ed[M];
int cal(bool fx)
{
int ret=;
for(int i=;i<=n;i++)
ret+=t[i][fx?b[i]:a[i]];
for(int i=;i<=m;i++)
{
int u=ed[i].x,v=ed[i].y;
ret+=t[fx?b[u]:a[u]][fx?b[v]:a[v]];
}
return ret;
}
int get_rd(db T)
{
ll ret=(rand()*-RAND_MAX)*T;
return ret%k;
}
void SA(db T)
{
int ys=cal(),ts; int deb=;
while(T>eps)
{
int p=rand()%n+,d=a[p]+get_rd(T), cnt=;
while(d==a[p]&&cnt<)d=a[p]+get_rd(T),cnt++;
d=Mx(d,); d=Mn(d,k); b[p]=d;
ts=cal();
if(ts<ys||exp((ts-ys)/T)*RAND_MAX<rand())
{
a[p]=d; ys=ts;
if(ts<ans)memcpy(prn,a,sizeof a);
}
b[p]=a[p]; T*=dec;
}
}
int main()
{
srand(time());
n=rdn();m=rdn();k=rdn();op=rdn();
for(int i=;i<=m;i++)
{ ed[i].x=rdn();ed[i].y=rdn();}
for(int i=;i<=n;i++)
for(int j=;j<=k;j++) t[i][j]=rdn();
for(int i=;i<=k;i++)
for(int j=;j<=k;j++) r[i][j]=rdn();
for(int i=;i<=n;i++)a[i]=b[i]=prn[i]=rand()%k+;
ans=cal();
for(int i=;i<=;i++)
SA();
for(int i=;i<=n;i++)printf("%d ",prn[i]);puts("");
return ;
}

LOJ 2557 「CTSC2018」组合数问题 (46分)的更多相关文章

  1. LOJ2557. 「CTSC2018」组合数问题

    LOJ2557. 「CTSC2018」组合数问题 这道题是我第一道自己做完的题答题.考场上面我只拿了41分,完全没有经验.现在才发现其实掌握了大概的思路还是不难. 首先模拟退火,通过了1,2,6,9, ...

  2. loj#2552. 「CTSC2018」假面

    题目链接 loj#2552. 「CTSC2018」假面 题解 本题严谨的证明了我菜的本质 对于砍人的操作好做找龙哥就好了,blood很少,每次暴力维护一下 对于操作1 设\(a_i\)为第i个人存活的 ...

  3. Loj #2554. 「CTSC2018」青蕈领主

    Loj #2554. 「CTSC2018」青蕈领主 题目描述 "也许,我的生命也已经如同风中残烛了吧."小绿如是说. 小绿同学因为微积分这门课,对"连续"这一概 ...

  4. Loj #2553. 「CTSC2018」暴力写挂

    Loj #2553. 「CTSC2018」暴力写挂 题目描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = ...

  5. loj #2143. 「SHOI2017」组合数问题

    #2143. 「SHOI2017」组合数问题   题目描述 组合数 Cnm\mathrm{C}_n^mC​n​m​​ 表示的是从 nnn 个互不相同的物品中选出 mmm 个物品的方案数.举个例子, 从 ...

  6. LOJ 2553 「CTSC2018」暴力写挂——边分治+虚树

    题目:https://loj.ac/problem/2553 第一棵树上的贡献就是链并,转化成 ( dep[ x ] + dep[ y ] + dis( x, y ) ) / 2 ,就可以在第一棵树上 ...

  7. LOJ 2555 「CTSC2018」混合果汁——主席树

    题目:https://loj.ac/problem/2555 二分答案,在可以选的果汁中,从价格最小的开始选. 按价格排序,每次可以选的就是一个前缀.对序列建主席树,以价格为角标,维护体积和.体积*价 ...

  8. LOJ 2554 「CTSC2018」青蕈领主——结论(思路)+分治FFT

    题目:https://loj.ac/problem/2554 一个“连续”的区间必然是一个排列.所有 r 不同的.len 最长的“连续”区间只有包含.相离,不会相交,不然整个是一个“连续”区间. 只有 ...

  9. LOJ 2552 「CTSC2018」假面——DP

    题目:https://loj.ac/problem/2552 70 分就是 f[i][j] 表示第 i 个人血量为 j 的概率.这部分是 O( n*Q ) 的:g[i][j][0/1] 表示询问的人中 ...

随机推荐

  1. eval方法遇到的问题

    工作中有这样的场景,一个表达式比如 2*2,计算结果是number,这样的为true,如果输入错误 2*@,这样的情况需要匹配为false. 这里使用的eval方法, type of (eval('2 ...

  2. Vagrant 手册之 Multi-machine 多机器

    原文地址 Vagrant 可以在一个 Vagrantfile 中定义并控制多个虚拟机.这就是"multi-machine"环境. 这些机器可以协同工作或互相关联.multi-mac ...

  3. 【ABAP系列】SAP ABAP基础-程序优化及响应速度之LOOP

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-程序优化及 ...

  4. Bootstrap 学习笔记11 按钮和折叠插件

     复选框: <div class="btn-group" data-toggle="buttons"> <label for="se ...

  5. Sublime Text3安装配置

    Sublime Text3的所有package都可在如下网站检索 https://packagecontrol.io/browse 以下是我的插件列表 CoolFormat 一款C\C++\C#\CS ...

  6. "CoolShell puzzle game" writeup

    地址:http://fun.coolshell.cn/ Fuck your brain 看到一大串符号,还以为是 js 代码,结果放到 Chrome 控制台执行没有任何结果,然后搜了一下发现有一门叫B ...

  7. VScode 常用快捷键 2019

    窗口操作 Ctrl + b      : 显示/隐藏左侧工作区文件目录 View   Appearance   show Activity bar : 最左侧工具栏 显示/隐藏 Preferences ...

  8. golang的数据类型之整型类型

    数据类型: 整数 : int, int32, int64, uint, uint32, uint64 字符串 : string 布尔:bool 浮点:float32 float64 uint 表示无符 ...

  9. Nacos-作为Sring cloud 注册发现

    Nacos:一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. https://nacos.io/zh-cn/index.html 功能: 动态服务配置 服务发现和管理 动态DNS服务 ...

  10. dp(不连续和)

      I - I HDU - 2845   Bean-eating is an interesting game, everyone owns an M*N matrix, which is fille ...