1. 程式人生 > >Codeforces Round #197 (Div. 2): C. Xenia and Weights(記憶化搜尋)

Codeforces Round #197 (Div. 2): C. Xenia and Weights(記憶化搜尋)

 

題意:

先輸入一個長度為10的01串,第i個數字為1表示你有重量為i的砝碼無數個,第i個數字為0表示你沒有重量為i的砝碼,你需要按照以下規則在一個一開始平衡的天平上放上m個砝碼

  • 第1個砝碼放在天平左邊,第2個砝碼放在天平的右邊,第3個砝碼放在天平左邊……依次交替,直到放完m個
  • 每次放完砝碼後,必須滿足天平往當前這一側傾斜(重量大於另一側)
  • 不能連續放兩次相同質量的砝碼

求出任意一組合法解,如果沒有輸出NO

 

思路:

dp[m][last][val]表示當前已經放了m個砝碼,上一次放的砝碼質量為last,且放完後天平的不平衡度為val的狀態是否已經搜過

搜出一組解就直接在DFS時輸出,搜不到就輸出NO

複雜度O(10*10*m)

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
int flag[12], dp[1005][12][12];
int Sech(int n, int last, int dis)
{
	int i;
	if(dp[n][last][dis])
		return 0;
	dp[n][last][dis] = 1;
	if(n==1)
	{
		if(last==dis)
		{
			printf("YES\n%d", last);
			return 1;
		}
		return 0;
	}
	if(dis>=last || dis==0)
		return 0;
	for(i=1;i<=10;i++)
	{
		if(flag[i]==0 || last==i)
			continue;
		if(Sech(n-1, i, last-dis))
		{
			printf(" %d", last);
			return 1;
		}
	}
	return 0;
}
int main(void)
{
	int i, n, j;
	for(i=1;i<=10;i++)
		scanf("%1d", &flag[i]);
	scanf("%d", &n);
	for(i=1;i<=10;i++)
	{
		if(flag[i]==0)
			continue;
		for(j=0;j<=i;j++)
		{
			if(Sech(n, i, j))
			{
				puts("");
				return 0;
			}
		}
	}
	printf("NO\n");
	return 0;
}