3只DP

马上要省选了呢、、、
应该快速突破一下、、、
今天的dp还是很水的题……
1.Noip:金明的预算方案。
大概就是有依赖的背包,考虑这个背包整体选不选,部分选不选即可。

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)
#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)
#define RD(i,x,n) for(int i = x; i <= n ; i ++)
#define CLR(a,b) memset(a,b,sizeof(a))
#define fl edge[i].f
#define vfl edge[i^1].f
#define v edge[i].to
using namespace std;
const int inf = 1 << 30;
typedef long long ll;
int read(){
    char ch = getchar();
    while(ch < '0' || ch > '9')ch = getchar ();
    int x = 0;
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar ();
    return x;
}
int n,m;
int f[20005];
int link[65][5];
int c[65],w[65],ct[65];
int main()
{
    CLR(link,-1);
    n = read();
    n /= 10;
    m = read();
    Rep(i,m){
        w[i] = read(),w[i] /= 10,c[i] = read(),c[i] *= w[i];
        link[i][0] = read();
    }
    CLR(ct,0);
    Rep(i,m)
        if(link[i][0])link[link[i][0]][++ ct[link[i][0]]] = i;

//  Rep(i,m)
//      printf("%d %d %d %d\n",link[i][0],link[i][1],link[i][2],c[i]);
    Rep(i,m)
        for(int j = n;j >= w[i];j --){
            if(!link[i][0]){
                f[j] = max(f[j],f[j - w[i]] + c[i]);
                if(ct[i] >= 1 && j >= w[i] + w[link[i][1]])f[j] = max(f[j - w[i] - w[link[i][1]]] + c[i] + c[link[i][1]],f[j]);
                if(ct[i] == 2){
                    if(j >= w[i] + w[link[i][1]] + w[link[i][2]])f[j] = max(f[j - w[i] - w[link[i][1]] - w[link[i][2]]] + c[i] + c[link[i][1]] + c[link[i][2]],max(f[j - w[i] - w[link[i][2]]] + c[i] + c[link[i][2]],f[j]));       
                    else if(j >= w[i] + w[link[i][2]])f[j] = max(f[j],f[j - w[i] - w[link[i][2]]] + c[i] + c[link[i][2]]);      
                }
            }
        }
    printf("%d\n",f[n] * 10);
    return 0;
}


2.更水的乌龟棋:
统计卡片个数,类似零一背包,考虑这张卡片选或不选。

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define Repp(i,n) for(int i = 0;i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)
#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)
#define RD(i,x,n) for(int i = x; i <= n ; i ++)
#define CLR(a,b) memset(a,b,sizeof(a))
#define fl edge[i].f
#define vfl edge[i^1].f
#define v edge[i].to
#define N 355
using namespace std;
const int inf = 1 << 30;
typedef long long ll;
int read(){
    char ch = getchar();
    while(ch < '0' || ch > '9')ch = getchar ();
    int x = 0;
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar ();
    return x;
}
int n ,m,seq[N],c[6];
int f[41][41][41][41];
int main()
{
    n = read(),m = read();
    Rep(i,n)
        seq[i] = read();
    Rep(j,m){
        int p = read();
        c[p] ++;
    }
    f[0][0][0][0] = seq[1];
    Repp(i,c[1])
        Repp(j,c[2])
            Repp(k,c[3])
                Repp(l,c[4])
                {
                //  printf("i : %d j : %d k : %d l : %d\n",i,j,k,l);
                    int len = i + j * 2 + k * 3 + l * 4 + 1;
                    if(i >= 1)f[i][j][k][l] = max(f[i - 1][j][k][l] + seq[len],f[i][j][k][l]);
                //  printf("%d ",f[i][j][k][l]);
                    if(j >= 1)f[i][j][k][l] = max(f[i][j - 1][k][l] + seq[len],f[i][j][k][l]);
                //  printf("%d ",f[i][j][k][l]);
                    if(k >= 1)f[i][j][k][l] = max(f[i][j][k - 1][l] + seq[len],f[i][j][k][l]);
                //  printf("%d ",f[i][j][k][l]);
                    if(l >= 1)f[i][j][k][l] = max(f[i][j][k][l - 1] + seq[len],f[i][j][k][l]);
                //  printf("%d\n",f[i][j][k][l]);
                }
    printf("%d\n",f[c[1]][c[2]][c[3]][c[4]]);
    return 0;
}

3.上一个搜索剪枝、、、
一群小精灵一起抄书,但是有些会发生冲突即不在一个集合,有字迹漂亮的也有不漂亮的,问最多能获得多少美观度。
数据规模:N<= 100;
直接暴搜超时,有一个很显然的剪枝:
之后的所有小精灵的字迹美观度之和<= ans 直接不理这个点、、、

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)
#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)
#define RD(i,x,n) for(int i = x; i <= n ; i ++)
#define CLR(a,b) memset(a,b,sizeof(a))
#define fl edge[i].f
#define vfl edge[i^1].f
#define v edge[i].to
#define N 65
using namespace std;
const int inf = 1 << 30;
typedef long long ll;
int read(){
    char ch = getchar();
    while(ch < '0' || ch > '9')ch = getchar ();
    int x = 0;
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar ();
    return x;
}
struct Edge{int next,to;}edge[100005];
int ans = 0,n,head[N],ct[N],val[N],cnt = 0;
void save(int a,int b){
    edge[cnt].next = head[a];
    edge[cnt].to = b;
    head[a] = cnt ++;
}
void dfs(int s,int sum){
    int m ;
    ans = max(ans,sum);
    RD(x,s,n){
        if(!ct[x]){
            m = 0;
            RepG(i,x)
                ct[v] ++;
            RD(i,x + 1,n)if(!ct[i])m += val[i];
            if(m + sum + val[x] <= ans){
                RepG(i,x)
                    ct[v] --;
                continue;
            }
            ct[x] = 1;
            dfs(x + 1,sum + val[x]);
            ct[x] = 0;
            RepG(i,x)
                ct[v] --;
        }
    }
}
int main()
{
    CLR(head,-1);
    n = read();
    Rep(i,n)val[i] = read();
    int a,b;
    while(~scanf("%d%d",&a,&b))
        save(a,b),save(b,a);
    dfs(1,0);
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值