9/16Contest H. Hsueh- and keyboard——Dijkstra

点这里

Hsueh- has a keyboard.
There is a string which has x characters in the textarea.
At present, Hsueh- wants to see a string of length exactly n in the textarea.
You can use the following operations to meet Hsueh-'s requirements.

  • Strike the keyboard once, enter a character.
  • Strike the keyboard twice(Ctrl + A), select all characters in the textarea.
  • Strike the keyboard twice(Ctrl + C), copy the selected character to the clipboard.
  • Strike the keyboard twice(Ctrl + V), paste the characters which in the clipboard(Do not empty the clipboard).
  • Strike the keyboard once(Backspace), delete character at the end of the textarea or delete the selected character if some characters are selected.
  • Hsueh- wants to know the minimum number of strokes required to see a string of length exactly n in the textarea.

What is different from your traditional perception is, if you press Ctrl + A to select all characters and then enter a character or paste some characters, the selected characters will not be deleted. In other words, if you select all characters in the textarea and then enter a character or paste some characters, it will not replace the selected characters but append the characters you enter or paste at the end.

Input
The first line contains two integers x,n(0≤x≤106,1≤n≤106), denoting the length of the string which originally appeared in the textarea and the length of the string which Hsueh- wants to see.

Output
Print a single integer in one line: the minimum number of strokes required to see a string of length exactly n in the textarea.

Example 1
input

1 4

output

3

Example 2
input

100 199

output

7


题意: 输入x和n表示希望你将长度为x的字符串,通过一些按键得到长度为n的字符串,求出最少的按键次数。0 <= x , n <= 106.你可以通过一下操作达到目的:

  • 按一下键盘,输入一个字符。
  • 按下键盘两次(Ctrl + A), 选中文本框中的所有字符。
  • 按下键盘两次(Ctrl + C), 复制选中的字符到剪贴板。
  • 按下键盘两次(Ctrl + V), 将剪贴板中的字符粘贴到文本框。
  • 按下键盘一次(Backspace), 删除文本框中的最后一个字符或者删除选中的字符,如果在这之前你按下了(Ctrl + A)选中了一些字符的话。

此处的操作和传统认知有所不同的是,如果你先按下了(Ctrl + A)选中了所有字符,再输入一个字符,或者粘贴剪贴板中的文字到文本框,那么它不会产生替换选中文字的效果,而是会直接当前字符串追加在后面。
或者你可以认为(Ctrl + A)只会对复制操作有效。

题解: 从x到n,求最少的按键次数,怎么有点像个最短路呢。那么尝试着建边:

  • 连接 i 和(i + 1):长度为1.(实际上为按一下键盘)
  • 连接 i 和(i - 1):长度为1.(实际上为按一下键盘)
  • 连接 i 和 0 :长度为3,(全选所有的字符,然后删除,一共按三下键盘)
  • 连接 i 和 i的所有倍数:长度为倍数 + 1.(全选所有的字符之后,要复制倍数-1次)

可能出现的问题:

  • 图的边界:单从x和n中取出较大值,作为图的的上限是不行的。建边的时候我们需要适当的扩充,太大可能造成MLE。程序中采用了int T = (x > n) ? x + 100 : n + 100;
  • 时间复杂度:其实我们在建边的时候,是建了一个很多边的图,需要在找到n处时退出程序,否则可能会TLE。

#include<bits/stdc++.h>
using namespace std;

#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;
int x, n, cnt;
int dis[N << 1], head[N << 1];
struct node{
	int id, w;
	node(){}
	node(int a, int b){	id = a; w = b;}
	bool operator<(const node &a)const{
		return a.w < w;}
};
struct edge{
	int v, w, next;
	edge(){}
	edge(int a, int b, int c){	v = a; w = b; next = c;}
} e[N * 20];

void addedge(int u, int v, int w){
	e[cnt].v = v, e[cnt].w = w, e[cnt].next = head[u];
	head[u] = cnt++;
}

void Dijkstra(int s){
	memset(dis, inf, sizeof dis);
	dis[s] = 0;
	priority_queue<node> Q;
	Q.push(node(s, 0));
	
	while(!Q.empty()){
		node p = Q.top(); Q.pop();
		int u = p.id;
		if(p.id == n)	break;
		for(int i = head[u]; ~i; i = e[i].next){
			int v = e[i].v, w = e[i].w;
			if(dis[v] > dis[u] + w){
				dis[v] = dis[u] + w;
				Q.push(node(v, dis[v]));
			}
		}
	}
	
	cout << dis[n] << endl;
}

void run(){
	cin >> x >> n;
	int T = (x > n) ? x + 100 : n + 100;
	
	memset(head, -1, sizeof head);
	for(int i = 0; i <= T; i++){
		addedge(i, i + 1, 1);
		addedge(i + 1, i, 1);
		addedge(i + 1, 0, 3);
		for(int j = 2; i * j <= T && i; j++){
			addedge(i, i * j, 2 + 2 * j);
		}
	}
	
	Dijkstra(x);
}

int main(){
	IOS;
	
	run();
	
	return 0;
}
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页