LOJ 2557 「CTSC2018」组合数问题 (46分)
题目: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分)的更多相关文章
- LOJ2557. 「CTSC2018」组合数问题
LOJ2557. 「CTSC2018」组合数问题 这道题是我第一道自己做完的题答题.考场上面我只拿了41分,完全没有经验.现在才发现其实掌握了大概的思路还是不难. 首先模拟退火,通过了1,2,6,9, ...
- loj#2552. 「CTSC2018」假面
题目链接 loj#2552. 「CTSC2018」假面 题解 本题严谨的证明了我菜的本质 对于砍人的操作好做找龙哥就好了,blood很少,每次暴力维护一下 对于操作1 设\(a_i\)为第i个人存活的 ...
- Loj #2554. 「CTSC2018」青蕈领主
Loj #2554. 「CTSC2018」青蕈领主 题目描述 "也许,我的生命也已经如同风中残烛了吧."小绿如是说. 小绿同学因为微积分这门课,对"连续"这一概 ...
- Loj #2553. 「CTSC2018」暴力写挂
Loj #2553. 「CTSC2018」暴力写挂 题目描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = ...
- loj #2143. 「SHOI2017」组合数问题
#2143. 「SHOI2017」组合数问题 题目描述 组合数 Cnm\mathrm{C}_n^mCnm 表示的是从 nnn 个互不相同的物品中选出 mmm 个物品的方案数.举个例子, 从 ...
- LOJ 2553 「CTSC2018」暴力写挂——边分治+虚树
题目:https://loj.ac/problem/2553 第一棵树上的贡献就是链并,转化成 ( dep[ x ] + dep[ y ] + dis( x, y ) ) / 2 ,就可以在第一棵树上 ...
- LOJ 2555 「CTSC2018」混合果汁——主席树
题目:https://loj.ac/problem/2555 二分答案,在可以选的果汁中,从价格最小的开始选. 按价格排序,每次可以选的就是一个前缀.对序列建主席树,以价格为角标,维护体积和.体积*价 ...
- LOJ 2554 「CTSC2018」青蕈领主——结论(思路)+分治FFT
题目:https://loj.ac/problem/2554 一个“连续”的区间必然是一个排列.所有 r 不同的.len 最长的“连续”区间只有包含.相离,不会相交,不然整个是一个“连续”区间. 只有 ...
- LOJ 2552 「CTSC2018」假面——DP
题目:https://loj.ac/problem/2552 70 分就是 f[i][j] 表示第 i 个人血量为 j 的概率.这部分是 O( n*Q ) 的:g[i][j][0/1] 表示询问的人中 ...
随机推荐
- JNI-java native interface(java本地接口)
什么是JNI java native interface(java本地接口) ABI: application binary interface (应用程序二进制接口) 为什么要使用JNI * 复用很 ...
- 【OpenGL】---认识CubeTexture
一.OpenGL Cube Texture 立方体纹理 立方体纹理是一种特殊的纹理技术,他用6幅二维贴图构成一个以原点为中心的纹理立方体.对于每个片段,纹理坐标(s,t,r)被当做三维向量看待,每个纹 ...
- 写的一个双向链表,测试OK
#include <stdio.h> #include <stdlib.h> #include <assert.h> typedef struct DoubleLi ...
- hash-散列笔记
散列基础与整数散列 散列(hash哈希)的基本思想--"将元素通过一个函数转换为整数,使该整数可以尽量唯一地代表这个元素".其中把这个转换函数称为散列函数H,元素在转换前为key, ...
- 2019/11/09 TZOJ
1001 Interesting Integers http://www.tzcoder.cn/acmhome/problemdetail.do?&method=showdetail& ...
- 进程池Pool的简单使用,同步异步的区别
#进程池 """ 当需要创建子进程数量不多的时候,可以直接利用multiprocessing 中的Process动态生成多个进程,但是如果上百甚至上千个任务, " ...
- #3831 TJOI2013单词
WOJ#3831 TJOI2013单词 题面 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. 输入 第一个一个整数 N ,表示有 ...
- luoguP1003 铺地毯 题解(NOIP2011)
luoguP1003 铺地毯 题目 #include<cstdio> #include<cstdlib> #include<cstring> #include&l ...
- Linux忘记密码怎么办
重启 Linux 系统主机并出现引导界面时,按下键盘上的 e 键进入内核编辑界面 在 linux16 参数这行的最后面追加"rd.break"参数,然后按下 Ctrl + X 组合 ...
- A Bug’s Life POJ - 2492(种类并查集)
题目链接 每次给出两个昆虫的关系(异性关系),然后发现这些条件中是否有悖论 就比如说第一组数据 1 2 2 3 1 3 1和2是异性,2和3是异性,然后说1和3是异性就显然不对了. 我们同样可以思考一 ...