WA on #1~#13 码风良好 贪心二分 悬关求调
查看原帖
WA on #1~#13 码风良好 贪心二分 悬关求调
578251
craft_07楼主2024/10/15 22:09

蒟蒻下发的大样例第一个就错了,感觉一个是初始化似乎没做好,另一方面思路也有一些问题。

求大神援助

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long LL;
const int N = 100003;
const int M = 11;

string s;
string NuLl;
int v[M];
int cnt[M];
int x[M][N];//表示数字i在数列中第j次出现的位置 
int cz[M];

long long sum,ans;

void print(int d)
{
	for(int i=1;i<=d;i++)
		printf("##%d",cz[i]);
	printf("\n");
}

bool ccheck(int d)
{
	int ccnt[M] = {0};
	for(int i = 1 ;i <= d ;i ++)
	{
		if( ++ccnt[cz[i]] > cnt[cz[i]] )
			return false;
	}
	return true;
}


void init();
void dfs(int);
void check(int);
int  find(int,int); // 返回从l开始 , 数字a第一次出现的位置 

int main()
{
	int C;
	scanf("%d", &C);
	int T;
	scanf("%d", &T);
	while(T--)
	{
		init();
		dfs(1);
		printf("%lld\n", ans);
	}
	return 0;
}

void init()
{
	s = NuLl;
	memset(v,sizeof(v),0);
	memset(cnt,sizeof(cnt),0);
	memset(x,sizeof(x),0x3f);
	memset(cz,sizeof(cz),0);
	sum = ans = 0;
	
	cin >> s;
	int l = s.size();
	s = '0' + s;
	for(int i = 1 ;i <= 9 ;i ++)
		scanf("%d", &v[i]);
	for(int i = 1 ;i <= l ;i ++)
	{
		int a = s[i] - '0';
		sum = sum + v[a];
		x[a][ ++ cnt[a] ] = i;
	}
	ans  = sum;
//	printf("#%d",ans);
}

void dfs(int d)
{
	if(d > 6) return ;
	for(int i = 1; i <= 9; i ++)
	{
		cz[d] = i;
		check(d);
		dfs(d + 1);
	}
}

void check(int d)
{
	if(ccheck(d) == false) return;
//	print(d);
	long long cost = 0;
	long long les = 0; 
	
	int l = 1;
	for(int i = 1; i <= d; i ++)
	{
		int a = cz[i];
		int cc = cnt[a];
		
		les += v[a];
		cost = cost * 10 + a;
		
		if(l > x[a][cc]) return; //如果当前查找的数字已经大于a最晚出现的位置 , 则找不到目标 
		
		l = find(l , a) + 1; 
	}
	if(sum + cost - les < ans) 
	{
		ans = sum + cost - les ;
//		print(d);
	}
//	ans = min(ans, sum + cost - les);
}

int find(int l,int a)
{
//	printf("\n %d ********* \n",l);
//	int ccc = 0;
	int ll = 1;
	int rr = cnt[a] + 1;
	int mid;
	while(ll < rr)
	{
		mid = (ll + rr) >> 1;
		long long p = x[a][mid];
		if(p < l) ll = mid + 1;
		else rr = mid;
//		if(ccc>10) return x[a][ll];
	}
//	printf("\n%d &&&&&&&&& \n",x[a][ll]);
	return x[a][ll];
}

//1
//1
//3158927982863528
//41423 65081 37768 31661 5606 86055 71796 46535 92370

//1
//1
//123
//1000 1000 1000 1 1 1 1 1 1 

//1
//1
//987654321
//100000 100000 100000 100000 100000 100000 100000 100000 100000 

2024/10/15 22:09
加载中...