zoukankan      html  css  js  c++  java
  • SRM 619

    easy: 
    假设每堆石头不全为1,那么每次我们总能取一堆石头分给另外两堆,堆数-1。而且新的局面肯定有一堆的个数大于1。
    于是,假设每堆石头数都为1 -> lose。否则的话推断堆数奇偶就可以(堆数==1要特判)

    medium:
    树形dp,dp[i][j],表示以i为根的子树分配完毕,而且i节点会j技能的最小花费。
    转移:枚举i点在自己的department所用的技能(k),然后用子节点的dp值建图。跑KM。
    得到最小花费后。枚举i节点会的还有一个技能(r),算出总花费然后更新dp[i][k]和dp[i][r]。


    hard:
    能够把这题也看成那种dp套dp的题目来做。

    。。


    先看一个naive版本号的题目:给两个串,问能否找到一种方案,两个串都删除两个位置的数,使得剩下的两个串同样。

    能够用这种dp表示方式来做:dp[i][3][3],表示A串能够匹配完前i个元素。而且A串已经删除了j个元素,B串已经删除了k个元素。dp值存的0/1。表示这种状态可不可达。
    (这个看上去比較奇怪可是他是能够work的。


    那么这道题能够一边假设两个串元素的值,一边做上面的dp。
    把上面后两维压成一个数9。然后做dp[i][1<<9]的dp,i还是上面的定义,1<<9表示对于眼下构造的串能否达到这9种状态。
    当然只通过A串的i位置元素和B串的i位置元素是没法推这种dp的。

    能够记录一下临近的元素的相互关系(记录临近的4个B串元素的相互关系就可以)

    dp[i][1<<9][k]。k是记录b[i-2],b[i-1],b[i],b[i+1]的相互关系(用最小表示法,然后哈希一下)

    递推:
    枚举b[i+2],然后再枚举a[i]。通过1<<9中每一个合法状态,用前面naive版本号的dp,得到新的1<<9的状态,然后b[i-1]~b[i+2]哈希成新的k。

    dp[i+1][newj][newk]+=dp[i][j][k]*add。假设b[i+2]和a[i]都是选择b[i-2]~b[i+1]中出现过的数。add就是1,否则add是选择的方案数。



    --------------------------------切割线---------------------------------------

    naive版本号的dp也能够这样子:dp[i][5]=A串删除最小次数。5表示A串和B串眼下相差几个字母(-2~2)
    这样我们1<<9的状态能够缩减成2*3*4*3*2(大概这么多)
    但事实上1<<9的写法假设写的姿势比較好,也几乎相同这些状态(没用状态会continue掉)

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <deque>
    #include <stack>
    #include <bitset>
    #include <algorithm>
    #include <functional>
    #include <numeric>
    #include <utility>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstring>
    
    using namespace std;
    
    class SimilarSequencesAnother {
    public:
    	int getCount(int, int);
    };
    
    long long pmod = 1000000009;
    long long dp[105][1 << 9][100];
    int Hash[5][5][5][5];
    int rHash[10005][4];
    int ed = 0;
    int add(int a[]) {
    	if (Hash[a[0]][a[1]][a[2]][a[3]] != -1)
    		return Hash[a[0]][a[1]][a[2]][a[3]];
    	Hash[a[0]][a[1]][a[2]][a[3]] = ed;
    	for (int i = 0; i < 4; ++i)
    		rHash[ed][i] = a[i];
    	ed++;
    	return ed - 1;
    }
    void get(int id, int a[]) {
    	for (int i = 0; i < 4; ++i)
    		a[i] = rHash[id][i];
    }
    int tmp[5], tt[4], flag[10];
    int SimilarSequencesAnother::getCount(int N, int bound) {
    	int i, j, k, r;
    	int jj, kk, p;
    	long long cost1, cost2;
    	long long m = bound;
    	memset(dp, 0, sizeof(dp));
    	memset(Hash, -1, sizeof(Hash));
    	ed = 0;
    	tt[0] = 0;tt[1] = 0;tt[2] = 0;tt[3] = 0;
    	add(tt);
    	dp[0][1][0] = m;
    	if (m >= 2) {
    		tt[0] = 0;tt[1] = 0;tt[2] = 0;tt[3] = 1;
    		add(tt);
    		dp[0][1][1] = m * (m - 1) % pmod;
    	}
    	for (i = 0; i < N; ++i) {
    		for (j = 0; j < (1 << 9); ++j) {
    			for (k = 0; k < ed; ++k) {
    				if (dp[i][j][k] == 0)
    					continue;
    				get(k, tmp);
    				int pn = max(tmp[0], max(tmp[1], max(tmp[2], tmp[3]))) + 1;
    				for (tmp[4] = 0; tmp[4] <= pn; ++tmp[4]) {
    
    					//把tmp[1]->tmp[4]拷贝到tt,并变成最小表达
    					memset(flag, -1, sizeof(flag));
    					int ttn = 0;
    					for (r = 0; r < 4; ++r) {
    						if (flag[tmp[r + 1]] == -1) {
    							flag[tmp[r + 1]] = ttn++;
    						}
    						tt[r] = flag[tmp[r + 1]];
    					}
    					////////////////////////////////////////
    					if (tmp[4] == pn)
    						cost1 = m - pn;
    					else
    						cost1 = 1;
    					if (cost1 <= 0)
    						continue;
    					kk = add(tt);
    					for (p = 0; p <= max(tmp[4] + 1, pn); p++) {//枚举A串当前字符
    						if (p == max(tmp[4] + 1, pn))
    							cost2 = m - max(tmp[4] + 1, pn);
    						else
    							cost2 = 1;
    						if (cost2 <= 0)
    							continue;
    						jj = 0;
    						for (r = 0; r < 9; ++r) {
    							if (j & (1 << r)) {
    								for (int movea = 0; movea < 2; ++movea)
    									for (int moveb = 0; moveb < 3; ++moveb) {
    										int xx = r % 3 + movea;
    										int yy = r / 3 + moveb;
    										if (xx > 2 || yy > 2)
    											continue;
    										if (movea) {
    											jj |= (1 << (yy * 3 + xx));
    											continue;
    										}
    										if (p == tmp[2 - xx + yy])
    											jj |= (1 << (yy * 3 + xx));
    									}
    							}
    						}
    						dp[i + 1][jj][kk] += dp[i][j][k] * cost1 % pmod * cost2
    								% pmod;
    						dp[i + 1][jj][kk] %= pmod;
    					}
    				}
    			}
    		}
    	}
    	long long ans = 0;
    	for (j = 1; j < (1 << 9); ++j) {
    		for (k = 0; k < ed; ++k) {
    			if (rHash[k][2] == 0 && rHash[k][3] == 0) {
    				ans += dp[N][j][k];
    				ans %= pmod;
    			}
    		}
    	}
    	return ans;
    }


  • 相关阅读:
    win10 安装anaconda+tensorflow
    CNN 理论
    mac 调出任何来源方法
    git忽略文件权限检查
    ios plist获取权限
    Vue-从入门到第三次世界大战_1
    libc++abi.dylib: terminating with uncaught exception of type NSException
    unity3d导出xcode项目使用afnetworking 3框架导致_kUTTagClassMIMEType 问题解决方案
    ios cannot use "@throw" with objective-c exceptions disabled 问题解决方案
    关于iOS APP转让
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/9934434.html
Copyright © 2011-2022 走看看