题目链接还可以看这里:http://my.youkuaiyun.com/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 card 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;
}
本文介绍了一个关于卡片游戏的算法问题,玩家需要通过特定策略来最小化剩余卡片数量。文章提供了完整的代码实现,采用记忆化搜索解决该问题。

被折叠的 条评论
为什么被折叠?



