题目: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. 使用 Select2 下拉框实现复选

    使用 Select2 下拉框实现复选 <!DOCTYPE html> <html> <head> <meta http-equiv="Content ...

  2. Drone - 安装,搭配 GitLab 下的配置和使用

    参考资料: Drone 官网地址:https://drone.io Drone 的 GitHub 地址:https://github.com/drone/drone 简介:https://imnerd ...

  3. 常见的网络设备:集线器 hub、网桥、交换机 switch、路由器 router、网关 gateway

    Repeater 中继器 Hub 集线器 bridge 网桥 switch 交换机 router 路由器 gateway 网关 网卡 参考资料: do-you-know-the-differences ...

  4. Vue作用域插槽:基本用法

    一 项目结构 二 App组件 <template> <div id="app"> <!-- 子组件 --> <user v-slot:de ...

  5. (appium+python)UI自动化_09_unittest批量运行测试用例&生成测试报告

    前言 上篇文章[(appium+python)UI自动化_08_unittest编写测试用例]讲到如何使用unittets编写测试用例,并执行测试文件.接下来讲解下unittest如何批量执行测试文件 ...

  6. 高德WMTS规则

    新版 http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1& ...

  7. .Net core 2.0 利用Attribute获取MVC Action来生成菜单

    最近在学习.net core的同时将老师的MVC5项目中的模块搬过来用,其中有一块就是利用Attribute来生成菜单. 一·首先定义Action实体 /// <summary> /// ...

  8. MySQL数据类型-整型

    ​ MySQL支持SQL标准整数类型integer(或INT)和SMALLINT.作为标准的扩展,MySQL还支持整数类型TINYINT.MEDIUMINT和BIGINT. 类型 所占字节 有符号最小 ...

  9. Flutter 仿滴滴出行App

    绿色出行 Flutter 仿滴滴出行App 地图:采用高德地图,仅简单完成了部分功能,基础地图,地址检索,逆地理编码. 界面:仿滴滴主界面,地图中心请求动效果,服务tabs展开效果,地址检索界面,城市 ...

  10. java_第一年_JavaWeb(3)

    ServletConfig对象 可以通过web.xml文件中的<init-param>标签来初始化参数,这些参数会在创建servlet实例时将其封装到ServletConfig对象中,并在 ...