CF1316 和 E

D的大意就是能否找到一个按题目要求的模拟的东西
首先一个数想要到达终点 他经过的点都是要和他一个终点的 并且终点的终点是他自己
那么就可以先把所有终点的终点是自己的 且 其他点的终点是他的终点的 dfs出来
如果是死循环的话 那么就先两两互相连 比如 左边的点到右 然后右边的点到左 这个时候在dfs找一下有没有和他们一样需要死循环的就行了

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 3100;

int a[N][N],flag[N][N];char out[N][N];
int b[N][N];
int xx[4] = {0,1,0,-1};
int yy[4] = {1,0,-1,0};

void dfs(int x,int y){
    flag[x][y] = 1;
    for(int i = 0; i < 4; i++){
        int dx = x + xx[i],dy = y + yy[i];
        if(flag[dx][dy]) continue;
        if(a[x][y] == a[dx][dy] && b[x][y] == b[dx][dy]){
            if(xx[i] == 1){
                out[dx][dy] = 'U';
            }else if(xx[i] == -1) out[dx][dy] = 'D';
            else if(yy[i] == 1) out[dx][dy] = 'L';
            else out[dx][dy] = 'R';
            dfs(dx,dy);
        }
    }
}

int main(){
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            scanf("%d",&a[i][j]);
            scanf("%d",&b[i][j]);
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            out[i][j] = 'A';
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == a[i][j] && j == b[i][j]){
                out[i][j] = 'X';
                dfs(i,j);
            }
        }
    }

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(flag[i][j]) continue;
            if(a[i][j] == -1 && a[i][j + 1] == -1){
                out[i][j] = 'R',out[i][j + 1] = 'L';
                flag[i][j + 1] = 1;
                dfs(i,j);
                dfs(i,j + 1);
            }else if(a[i][j] == -1 && a[i + 1][j] == -1){
                out[i][j] = 'D',out[i + 1][j] = 'U';
                flag[i + 1][j] = 1;
                dfs(i,j);
                dfs(i + 1,j);
            }
        }
    }

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(out[i][j] == 'A'){
                cout << "INVALID" << endl;
                return 0;
            }
        }
    }

    cout << "VALID" << endl;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            cout << out[i][j];
        }
        cout << endl;
    }

    return 0;
}

E一看题目就能知道是个状压dp但是如何去处理K个人的那一部分呢 我们可以sort一下然后将大的观众放在前面 如果这个人没有被选到队伍里面 并且观众不够的话 那么他必然是观众 因为后面的观众值都没他大 所以只要一个状压dp就完事了

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 1e5 + 10;
typedef long long ll;

struct node{
    ll gz,dy[10];
    bool operator < (const node &p)const{
        return gz > p.gz;
    }
}a[N];

ll dp[N][1 << 8],sum = 0;

int main(){
    int n,p,k;
    cin >> n >> p >> k;
    for(int i = 1; i <= n; i++){
        scanf("%lld",&a[i].gz);
    }

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= p; j++){
            scanf("%lld",&a[i].dy[j]);
        }
    }

    sort(a + 1,a + n + 1);
    memset(dp,-0x3f,sizeof dp);
    dp[0][0] = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 0; j < (1 << p); j++){
            dp[i][j] = dp[i - 1][j];
        }
        for(int j = 0; j < (1 << p); j++){
            int h = 0;
            for(int d = 0; d < p; d++){
                if((j & (1 << d)) == 0){
                    dp[i][j ^ (1 << d)] = max(dp[i - 1][j] + (a[i].dy[d + 1]),dp[i][j ^ (1 << d)]);
                }else ++h;
            }
            if(i - h <= k){
                dp[i][j] = max(dp[i][j],dp[i - 1][j] + a[i].gz);
            }
        }
    }

    cout << dp[n][(1 << p) - 1] <<endl;

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值