zoukankan      html  css  js  c++  java
  • dp1~10

    $t1.P2704 $ 炮兵阵地(状压)** *再看一遍

    由数据范围易知,状压,每个炮兵会影响前两行,所以dp状态里要带前一行的状态和当前行状态,不考虑前两行是因为转移是,确定前一行合法,前两行会被当做前一行的前一行

    (dp[L][S][i])表示当前在第(i)行,当前行状态为(S),上一行状态为(L)

    (dp[L][S][i]=max(dp[L][S][i],dp[last~L][L][i-1]+sum[S]))

    判断山丘,令平原为(0),山丘为(1),(S&a[i])不为(0),不合法

    判断左右两个距离在两格之内

    (S&(S<<1))(S&(S<<2)) 不为0,不合法

    判断每一列之前两行

    (S&L)(S&last~L) 不为(0)不合法

    代码不粘

    (t2.)排兵布阵

    背包模型,城堡看为背包,兵力看为代价,获胜场数*第几个城堡为价值

    (f[j])表示已经派出(j)兵力的最大价值,枚举城堡(i),将每个人派出的兵力排序后,记第(k)个人派出的兵力为(a[i][k]),由于已经排好序,能打败第(k)个敌人就能打败第(k-1)个,因此枚举敌人(k),贪心地派出刚好比他的兵力两倍多(1)的兵力转移

    (f[j]=max(f[j],f[j-(2*a[i][k]+1)]+i*k))

    int main(){
    	read(S); read(n); read(m);
    	int i,j,k;
    	for(i = 1;i <= S;++i)
    		for(j = 1;j <= n;++j)
    			read(a[j][i]);
    	for(i = 1;i <= n;++i) 
    		sort(a[i] + 1,a[i] + 1 + S);
    	for(i = 1;i <= n;++i)
    		for(j = m;j >= 0;--j)
    			for(k = 1;k <= S;++k)
    				if(j > 2*a[i][k])
    					f[j] = max(f[j],f[j - 2*a[i][k] -1] + i*k);
    	printf("%d",f[m]);
    }
    

    (t3.)病毒感染

    这是绿题吗???,可以评个蓝紫题 另外(Orz) (SyadouHayami)神仙

    可以发现往左走就要把左边所有没治愈的村庄治愈

    过程可以分为几段,每段以任意顺序治愈后回到该段起点,再治愈其它段

    (f_i)表示治愈前(i)个村庄最小死亡人数,(s_i=sumlimits_{j=1}^i a_i)(w_{i,j})为从(i)出发治愈([i,j])所有村庄再返回(i)的最小死亡人数,转移方程为

    [f_i=minlimits_{j<i}{f_j+[j ot=0](s_n-s_j)+w_{j+1,i}+[i ot=n](i-j-1)(s_n-s_i)} ]

    (f_0=0)

    (w_{i,j})(w_{i+1,j})转移,枚举(i)开始治不治

    [w_{i,j}=w_{i+1,j}+min egin{cases} 2(s_n-s_i)+(s_n-s_j)\ 3(j-i)a_i+(s_n-s_i)+2(s_n-s_j)\ end{cases} ]

    (w_{i,i}=s_n-s_i)

    int main(){
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i) scanf("%d",&a[i]),s[i] = s[i-1] + a[i];
    	for (int j = 1;j <= n;++j) {
            w[j][j] = s[n]-s[j];
            for (int i = j-1;i;--i)
                w[i][j] = w[i+1][j] + min(2*(s[n]-s[i]) + s[n]-s[j],3*a[i]*(j-i) + 2*(s[n]-s[j]) + s[n]-s[i]);
        }
        memset(f,0x3f,sizeof(f)),f[0]=0;
        for(int i = 1;i <= n;++i)
            for(int j = 0;j < i;++j)
                f[i] = min(f[i],f[j] + (j != 0)*(s[n]-s[j]) + w[j+1][i] + (i-j-1)*(s[n]-s[i]));
        printf("%lld
    ",f[n]);
    }
    

    (t4) (Game~~on~~a~~Tree)

    题意:

    一张无向图, (Alice)选择从某处开始放一个棋子,然后 (Bob)(Alice) 依次移动这个棋子,但是不能走到到过的地方,无法操作者败。

    假如做过P1623,可能会联想到要找树的匹配

    分类讨论

    假如树是完美匹配的,后手只要走先手的完美匹配点即可,先手会失败

    树没有完美匹配,找出树的最大匹配((1,2),(3,4)),假如先手从一个没在最大匹配的点开始,后手不可能再走到一个没有在最大匹配的点,先后手转换

    (f_x)表示(x)子树中多少点没有匹配即可

    (令cnt=sum_{以i为根的后代}) (f_i=cnt-1(cnt>0))(f_i=1(cnt=0))

    #include<cstdio>
    #include<iostream>
    using namespace std;
    inline int read(){
    	int x = 0;char c = getchar();
    	while(!isdigit(c)) c = getchar();
    	while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    	return x;
    }
    const int N = 1e5 + 10;
    struct edge{int to,next;}e[N<<1]; int head[N],tot,f[N];
    inline void add(int u,int v){
    	e[++tot] = (edge){v,head[u]}; head[u] = tot;
    }
    void dfs(int x,int fa){
    	f[x] = -1;
    	for(int i = head[x];i;i = e[i].next){
    		int v = e[i].to;
    		if(v == fa) continue;
    		dfs(v,x); f[x] += f[v];
    	}
    	if(f[x] < 0) f[x] = -f[x];
    }
    int main(){
    	int n;scanf("%d",&n);int u,v;
    	for(int i = 1;i < n;++i){
    		u = read(); v = read();
    		add(v,u); add(u,v);
    	} dfs(1,0);
    	puts(f[1] ? "Alice" : "Bob");
    }
    

    (t5:) 取石子游戏

    (Nim)游戏:各堆石子异或和为(0),先手必败,否则必胜

    如果第一堆石子数目大于其它石子异或和,先手可以拿走大于的数量,转为必胜态

    所以要让第一堆石子数(le)其它石子异或和

    定义(f[i][j])为前(i)堆石子(xor)和为(j)的方案数,注意转移需要跳过枚举的第一堆石子,异或和最大为256

    (O(n^3))

    int f[205][260],a[205],n,ans;
    int main(){
    	scanf("%d",&n);
    	for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
    	f[0][0] = 1;
    	for(int i = 1;i <= n;++i){
    		for(int j = 1;j <= n;++j)
    			for(int k = 0;k < 256;++k){
    				if(i == j) f[j][k] = f[j-1][k];//跳过 
    				else f[j][k] = (f[j-1][k] + f[j-1][k^a[j]]) % mod;
    			}
    		for(int j = a[i];j <= 255;++j) ans += f[n][j],ans %= mod;
    	}
    	printf("%d",ans);
    }
    
  • 相关阅读:
    小阳买水果
    单调队列+dp
    最长的合法序列(栈+dp)
    A. 打印收费
    数位dp(K好数)
    Floyd(选地址)
    最短路计数
    线段树维护区间01
    解密(拓展欧几里的)
    树、森林的遍历
  • 原文地址:https://www.cnblogs.com/shikeyu/p/13778449.html
Copyright © 2011-2022 走看看