CF GYM 100703G Game of numbers

题意:给n个数,一开始基数为0,用这n个数依次对基数做加法或减法,使基数不超过k且不小于0,输出最远能运算到的数字个数,输出策略。

解法:dp。dp[i][j]表示做完第i个数字的运算后结果为j的可能性,可能为1,不可能为0,于是得到状态转移方程dp[i][j] = dp[i - 1][j - a[i]] | dp[i - 1][j + a[i]],当被转移的状态不在0~k之间时特判。dp时记录路径。

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
bool dp[1005][1005];
bool path[1005][1005];
int a[1005];
int main()
{
    int n, k;
    while(~scanf("%d%d", &n, &k))
    {
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        memset(dp, 0, sizeof dp);
        memset(path, 0, sizeof path);
        dp[0][0] = 1;
        int ans = 0;
        int pos = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j <= k; j++)
            {
                if(j - a[i] < 0 && j + a[i] > k)
                    continue;
                if(j - a[i] < 0)
                {
                    dp[i][j] = dp[i - 1][j + a[i]];
                    path[i][j] = 0;
                }
                else if(j + a[i] > k)
                {
                    dp[i][j] = dp[i - 1][j - a[i]];
                    path[i][j] = 1;
                }
                else
                {
                    dp[i][j] = (dp[i - 1][j - a[i]] | dp[i - 1][j + a[i]]);
                    if(dp[i - 1][j - a[i]])
                        path[i][j] = 1;
                }
                if(dp[i][j])
                {
                    ans = i;
                    pos = j;
                }
            }
            if(ans != i)
                break;
        }
        printf("%d
", ans);
        vector <bool> v;
        for(int i = ans; i > 0; i--)
        {
            v.push_back(path[i][pos]);
            if(path[i][pos])
                pos -= a[i];
            else
                pos += a[i];
        }
        int len = v.size();
        for(int i = len - 1; i >= 0; i--)
        {
            if(v[i])
                printf("+");
            else
                printf("-");
        }
        puts("");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/Apro/p/4685436.html