google codejam 2014年9月15日场C题题解

题目链接还可以看这里:http://my.csdn.net/my/album/detail/1785607

Problem C. Card Game

Confused? Read the quick-start guide.
Small input
9 points
Solve C-small
You may try multiple times, with penalties for wrong submissions.
Large input
17 points
You must solve the small input first.
You have 8 minutes to solve 1 input file. (Judged after contest.)
Problem

Bob is fond of playing cards. On his birthday party, his best friend Alice gave him a set of cards.

There are N cards and each card contains an integer number. He put the cards from left to right on a desk and wants to discard some of them. Before he discards any cards, he will choose a number K. At each time, he always chooses 3 adjacent cards to discard, and we assume that the numbers on each car
d from left to right are a, b and c. Bob guarantees that

c - b = b - a = K
Bob want to know what is the smallest number of cards he can be left with at the end. If he ever has a choice of which cards to discard, he chooses the cards that will leave him with the fewest cards at the end.

Input

The first line of the input gives the number of test cases, T. T test cases follow.

Each test cases contains two lines. The first line of each test case contains two integers: the number of cards N and the number K Bob chooses. The second line contains N integers a1, a2, ..., aN the numbers on the cards from left to right.

Output

For each test case, output one line containing "Case #x: y", where x
 is the test case number (starting from 1) and y is the smallest number of cards Bob can be left with after he has discarded everything he can.

Limits

1 ≤ T ≤ 100.
1 ≤ ai ≤ 106(1 ≤ i ≤ N).
1 ≤ N ≤ 100.
Small dataset

K = 0.
Large dataset

1 ≤ K ≤ 106.
Sample


Input 
 
Output 
 
2
6 0
4 4 3 3 3 4
5 1
3 1 2 3 4

Case #1: 0

Case #2: 2

使用记忆化搜索:f[i][j]表示i到j的结果

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 110;
int dp[maxn][maxn] , a[maxn];
bool vis[maxn][maxn];
int N , K;
int dfs(int L,int R) {
    if(L > R) return 0;
    if(vis[L][R]) return dp[L][R];
    vis[L][R] = true;
    if(R-L+1 <= 2) return dp[L][R] = (R-L+1);
    int Min = R-L+1;
    for(int i=L;i<R;i++) {
        int tmp = dfs(L,i) + dfs(i+1,R);
        if(tmp < Min) Min = tmp;
    }
    int mid = R-2 , tmp = R-L+1;
    if(mid > L && dfs(mid,R) == 0) tmp = min(tmp,dfs(L,mid-1));
    mid = L+2;
    if(mid < R && dfs(L,mid) == 0) tmp = min(tmp,dfs(mid+1,R));
    Min = min(Min , tmp);
    for(int i=L+1;i<R;i++) {
        if(dfs(L+1,i-1)==0 && dfs(i+1,R-1)==0 && a[i]-a[L]==K && a[R]-a[i]==K) return dp[L][R] = 0;
    }
    return dp[L][R] = Min;
}
void debug() {
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=N;j++) printf("%4d ",dp[i][j]);
        puts("");
    }
}
int main() {
    int T ,cas = 1;
    scanf("%d" , &T);
    while(T--) {
        scanf("%d%d" ,&N,&K);
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=N;i++) scanf("%d" , &a[i]);
        int ans = dfs(1,N);
        printf("Case #%d: %d\n" , cas++ , ans);
        //debug();
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值