TC SRM661 div2

来源:互联网 发布:星际淘宝网 编辑:程序博客网 时间:2024/05/21 04:40

今天本来最初的想法是开 SRM661 div1 的500分题,后来比较悲伤的是,想了一会儿似乎还是没有思路Q=Q。确切的说应该是没有catch到重点才对。同时也因为 SRM661 的题解还没出~ 既然这样的话,我就再来一发div2 练个手什么的好啦~23333

另外最近在空间说《大圣归来》国产动漫危机博同情什么的,又看到了熟悉的论调--“你没看到xxx那么努力么”,《大圣归来》我还没看因此不敢妄加评论,但是对于这种言论我只想说,谁都在努力,凭什么你努力了就应该获得回报?  如果你在那么努力了之后还是差劲的可以,那就请放弃吧,因为不合适。【虽然言辞过激了一点,但是只是想到自己这么多年来的生活,难免对于这种论调深恶痛绝。

然后开始言归正传:~

(一)

题意:给你一张图,图上使用o来表示沙子,用x表示固定的砖块,.表示空格,因为重力作用,沙子会沿着空格往下漏,遇到砖块就不能再往下了,求稳定之后整个图的状态是怎样的,用以下例子来说明:

1.输入状态:                                                          2.最终状态:

ooooo ..o..

..x.. ..x.o

....x ....x

..... .....

....o oo.oo


思路的话 并没有什么特别的,直接模拟就好,但是要注意顺序,对于每一列的话,先判断处于下方的沙子,在判断处于上方的沙子。贴个代码xD

vector <string> simulate(vector <string> board) {int n=board.size();int m=board[0].size();char bo_ma[55][55];char re_ma[55][55];for (int i=0;i<n;i++)for (int j=0;j<m;j++)bo_ma[i][j]=board[i][j];memset(re_ma,0,sizeof(re_ma));for (int col=0;col<m;col++)for (int row=n-1;row>=0;row--){if (bo_ma[row][col]=='.')continue;else if (bo_ma[row][col]=='x')continue;else{int bot=row;while (bot+1<n && bo_ma[bot+1][col]=='.')bot++;if (bot!=row){bo_ma[bot][col]='o';bo_ma[row][col]='.';}}}vector <string> ret;ret.clear();for (int i=0;i<n;i++){string tmp="";for (int j=0;j<m;j++)tmp+=bo_ma[i][j];ret.push_back(tmp);}return (ret);}


(二)

题意:已知有2*N个点,分为2行,对于每一行而言都是一条链,给出相邻两点之间的距离。之后需要你在第一条路中选择K个点,使之与第二条路的对应点相连之后构成的无向图,记对于以此法构造出无向图中两点之间距离最远为d,求使得d的最小值可以是多少?

噗,我觉得我题意也没有描述清楚但是看下图应该可以理解题意【他喵的 我最近语文好烂Q=Q


上图是 N=6 K=4 的情况 最终 d=4

然后 我用的方法简直暴力的我自己都不敢直视了Q=Q,我看到N最大值为11,直接通过位运算枚举所有可能的连线方法,然后用floyd暴力求解最长距离,这样的复杂度应该是

O(2^N*N^3)级别的,真是我自己都给吓哭了,但是反正最后就这样跌跌撞撞的过了,也算好吧XD

int gra[55][55];int n;int fin;int floyd() {int maxn = -1;int f_gra[55][55];for (int i=0;i<2*n;i++)for (int j=0;j<2*n;j++)f_gra[i][j]=gra[i][j];for (int k = 0; k < 2 * n; k++)for (int i = 0; i < 2 * n; i++)for (int j = 0; j < 2 * n; j++)if (f_gra[i][k] != -1 && f_gra[k][j] != -1) {if (f_gra[i][j] == -1)f_gra[i][j] = f_gra[i][k] + f_gra[k][j];elsef_gra[i][j] = min(f_gra[i][j], f_gra[i][k] + f_gra[k][j]);}for (int i = 0; i < 2 * n; i++)for (int j = 0; j < 2 * n; j++)maxn = max(maxn, f_gra[i][j]);return (maxn);}int check(int sta) {int num = 0;for (int i = 0; i < n; i++)if ((sta & (1 << i)) != 0)num++;return (num);}void modi_map(int sta, int val) {for (int i = 0; i < n; i++)if ((sta & (1 << i)) != 0)gra[i][i + n] = gra[i + n][i] = val;}int minDiameter(vector<int> a, vector<int> b, int K) {n = a.size();n++;memset(gra, -1, sizeof(gra));for (int i = 0; i < 2 * n; i++)gra[i][i] = 0;for (int i = 0; i < n - 1; i++)gra[i][i + 1] = gra[i + 1][i] = a[i];for (int i = n; i < 2 * n - 1; i++)gra[i][i + 1] = gra[i + 1][i] = b[i - n];fin = -1;//printf("%d\n",gra[0][1]);for (int i = 0; i < (1 << n); i++)if (check(i) == K) {modi_map(i, 0);/*if (i == 27) {for (int p = 0; p < 2 * n; p++)for (int q = p; q < 2 * n; q++)if (gra[p][q] != -1)printf("node %d ---> node %d    %d\n", p, q,gra[p][q]);}*///printf("sta ++++ %d\n",gra[0][1]);int tmp = floyd();if (fin == -1)fin = tmp;elsefin = min(fin, tmp);modi_map(i, -1);}return (fin);}


(三)

题意:大概就是你现在有K种颜色可以对N个点进行染色,染色之后对于点i与点j如果有i<j并且他们异色,那么你可以在他们之间连一条边,也可以不连,但是一个点的出度最多只能是1,入度没有限制。下图展示了  N=3  K=2 的情况:



思路:第一眼看上去,这简直是排列组合的题啊,然而做到一半就感觉不对了,包括序号限制,包括出度限制,这限制有点多,如果用排列组合来想的话是很困难的一件事儿。然后就调转枪口,准备开始用dp开始写,dp毕竟是我所有题型中写的比较好的题了吧,首先分析状态,因为K最大值只能取到3,并且N最大值为100,因此就考虑用3维的来做了。因为明显的可以知道,对于某个点而言,他究竟能连出多少条边,能拓展出多少种状态只取决与之前与他不同色的个数有多少,因此状态

f[i][j][k]表示到目前阶段为止,出现颜色1,2,3的个数为i,j,k     可以很明确的知道,如果当前点为p 那么一定有 i+j+k==p   状态确定之后转移也是一气呵成~

f[i+1][j][k]+=f[i][j][k]*(j+k+1) f[i][j+1][k]+=f[i][j][k]*(i+k+1)f[i][j][k+1]+=f[i][j][k]*(i+j+1)

简洁明了~  这三题中我也只对这题感觉自己做的比较满足~2333

然后代码~

<span style="white-space:pre"></span>long long f_2[105][105];long long f_3[105][105][105];int countWays(int N, int K) {if (K==1)return (1);else if (K==2){memset(f_2,0,sizeof(f_2));f_2[0][0]=1;for (int st=0;st<N;st++)for (int fi=0;fi<=st;fi++){int se=st-fi;if (f_2[fi][se]!=0){f_2[fi+1][se]=f_2[fi+1][se]+f_2[fi][se]*(se+1);f_2[fi+1][se]%=MOD;f_2[fi][se+1]=f_2[fi][se+1]+f_2[fi][se]*(fi+1);f_2[fi][se+1]%=MOD;}}long long ans=0;for (int i=0;i<=N;i++){ans=ans+f_2[i][N-i];ans%=MOD;}return (ans);}else if (K==3){memset(f_3,0,sizeof(f_3));f_3[0][0][0]=1;for (int st=0;st<N;st++)for (int fi=0;fi<=st;fi++)for (int se=0;se+fi<=st;se++){int th=st-fi-se;if (f_3[fi][se][th]!=0){f_3[fi+1][se][th]=f_3[fi+1][se][th]+f_3[fi][se][th]*(se+th+1);f_3[fi+1][se][th]%=MOD;f_3[fi][se+1][th]=f_3[fi][se+1][th]+f_3[fi][se][th]*(fi+th+1);f_3[fi][se+1][th]%=MOD;f_3[fi][se][th+1]=f_3[fi][se][th+1]+f_3[fi][se][th]*(fi+se+1);f_3[fi][se][th+1]%=MOD;}}long long ans=0;for (int i=0;i<=N;i++)for (int j=0;j<=N;j++){ans=ans+f_3[i][j][N-i-j];ans%=MOD;}return (ans);}}

嗯 ~如果能每天都刷刷tc的话   真的是很好的一件事儿~  LightOj 最近老是时不时挂掉一下~稍微有点头疼,等到适当的时候一定要准备开div1 了。 今天就差不多这样吧~稍微有点累呢!

0 0
原创粉丝点击